There is a table with below structure:
ID XID RChange
1 1 1
2 2 1
3 3 1
4 1 0
5 2 0
6 3 1
ID column is an identity column
XID column will have some values repeating
RChange will have either 1 or 0
I need those rows from the table with RChange column value changing from 1 to 0 with same XID
i.e. in the above table, for XID 1 and 2 RChange value has changed from 1 to 0 but for XID 3 it has changed from 1 to 1.
So, I need to write a query which will retrieve
ID XID RChange
4 1 0
5 2 0
So, please help me with your ideas.
You have not included a timestamp so I am assuming the ID column will determine the order.
;WITH byXID AS
(
SELECT ID, XID, RChange, ROW_NUMBER() OVER(PARTITION BY XID ORDER BY ID) rn
FROM Table1
)
SELECT t1.ID, t1.XID, t1.RChange
FROM byXID t1
INNER JOIN byXID t0 ON t1.XID = t0.XID AND t0.rn = t1.rn - 1
WHERE t1.RChange = 0 AND t0.RChange = 1
SQL Fiddle demo
This is another approach:
SELECT t2.ID, t2.XID, t2.RChange
FROM Table1 t1 JOIN Table1 t2
ON t1.XID = t2.XID
WHERE t1.RChange = 1 AND t2.RChange = 0
Sql fiddle demo (Thanks #Ic. for the fiddle)
Related
I have a set of data that I want to classify into groups based on a prior record id existing on the newer rows. The initial record of the group has a prior sequence id = 0.
The data is as follows:
customer id
sequence id
prior_sequence id
1
1
0
1
2
1
1
3
2
2
4
0
2
5
4
2
6
0
2
7
6
Ideally, I would like to create the following grouping column and yield the following results:
customer id
sequence id
prior sequence id
grouping
1
1
0
1
1
2
1
1
1
3
2
1
2
4
0
2
2
5
4
2
2
6
0
3
2
7
6
3
I've attempted to utilize island gap logic utilizing the ROW_NUMBER() function. However, I have been unsuccessful in doing so. I suspect the need here is more along the lines of a recursive CTE, which I am attempting at the moment.
I agree that a recursive CTE will do the job. Something like:
WITH reccte AS
(
/*query that determines starting point for recursion
*
* In this case we want all records with no prior_sequence_id
*/
SELECT
customer_id,
sequence_id,
prior_sequence_id,
/*establish grouping*/
ROW_NUMBER() OVER (ORDER BY sequence_id) as grouping
FROM yourtable
WHERE prior_sequence_id = 0
UNION
/*join the recursive CTe back to the table and iterate*/
SELECT
yourtable.customer_id,
yourtable.sequence_id,
yourtable.prior_sequence_id,
reccte.grouping
FROM reccte
INNER JOIN yourtable ON reccte.sequence_id = yourtable.prior_sequence_id
)
SELECT * FROM reccte;
It looks like you could use a simple correlated query, at least given your sample data:
select *, (
select Sum(Iif(prior_sequence_id = 0, 1, 0))
from t t2
where t2.sequence_id <= t.sequence_id
) Grouping
from t;
See Example Fiddle
I have a data set produced from a UNION query that aggregates data from 2 sources.
I want to select that data based on whether or not data was found in only of those sources,or both.
The data relevant parts of the set looks like this, there are a number of other columns:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
1
135
1
5
1
135
2
6
1
135
3
7
2
111
1
8
2
135
1
The [preference] column combined with the [group] column is what I'm trying to filter on, I want to return all the rows that have the same [preference] as the MIN([preference]) for each [group]
The desired output given the data above would be rows 1 -> 6
The [preference] column indicates the original source of the data in the UNION query so a legitimate data set could look like:
row
preference
group
position
1
1
111
1
2
1
111
2
3
1
111
3
4
2
111
1
5
2
135
1
In which case the desired output would be rows 1,2,3, & 5
What I can't work out is how to do (not real code):
SELECT * WHERE [preference] = MIN([preference]) PARTITION BY [group]
One way to do this is using RANK:
SELECT row
, preference
, [group]
, position
FROM (
SELECT row
, preference
, [group]
, position
, RANK() OVER (PARTITION BY [group] ORDER BY preference) AS seq
FROM t) t2
WHERE seq = 1
Demo here
Should by doable via simple inner join:
SELECT t1.*
FROM t AS t1
INNER JOIN (SELECT [group], MIN(preference) AS preference
FROM t
GROUP BY [group]
) t2 ON t1.[group] = t2.[group]
AND t1.preference = t2.preference
Given the following table:
Column1 Column2 idx
-------------------
1 1 0
2 1 0
3 2 0
4 3 0
5 3 0
1 3 0
How could I increase the idx column dependent on column2 in SQL Server and Oracle with an UPDATE statement?
I would like to have:
Column1 Column2 idx
--------------------
1 1 0
2 1 1
3 2 0
4 3 0
5 3 1
1 3 2
Thank you!
This (or similar) approach should work for both:
;with x as (
select idx, row_number() over(partition by Column2 order by Column1) as new_idx
from tbl
)
update x set idx = new_idx
(Here I assume that there is a typo in 6th row for Column1 - if not, there should be something else for ordering)
With Oracle you need a MERGE statement for this:
merge into x using (
select rowid as rid,
row_number() over(partition by Column2 order by Column1) as new_idx
from tbl
) t on (t.rid = x.rowid)
when matched then
set idx = t.new_idx;
Instead of using rowid you can replace the join with the primary key columns of the table.
I can't seem to get this one. So I have a table like this:
RowID UserID Type Data
1 A A 1
2 A A 2
3 A B 1
4 A B 2
5 B A 1
6 B A 2
7 B B 1
8 B B 2
And I need to group this table by UserID and Type and then return the RowID for the record in each group that holds the MIN value in the Data column.
So for my result set would be:
1
3
5
7
For SQL Server >= 2005, you can do:
select RowID
from (
select RowID,
Rank() over (Partition BY UserID, Type
order by Data) as Rank
from MyTable
) tmp
where Rank = 1
SQL Fiddle Example
For SQL Server < 2005, you can do:
select t.RowID
from MyTable t
inner join (
select UserID, Type, min(Data) as MinData
from MyTable
group by UserID, Type
) tm on t.UserID = tm.UserID and t.Type = tm.Type
and t.Data = tm.MinData
SQL Fiddle Example
I have a temp table which has two columns: one is Name and another RecordNumber. They looks like below:
Name RecordNumber Rownum
EMEA-1111-SCHD-1 0 1
EMEA-12362-SCHD-1 0 2
EMEA-12362-SCHD-1 0 3
EMEA-12362-SCHD-1 0 4
EMEA-12362-SCHD-1 0 5
EMEA-2191-SCHD-1 0 6
EMEA-2191-SCHD-1 0 7
EMEA-2191-SCHD-1 0 8
I need to update column "RecordNumber" with increment number starting with 1. Let say for EMEA-1111-SCHD-1 only one record, so RecordNumber should be updated to 1. For EMEA-12362-SCHD-1 four records, so RecordNumber should be updated to 1,2,3,4 accordingly. Basically, I need to have a result as:
Name RecordNumber Rownum
EMEA-1111-SCHD-1 1 1
EMEA-12362-SCHD-1 1 2
EMEA-12362-SCHD-1 2 3
EMEA-12362-SCHD-1 3 4
EMEA-12362-SCHD-1 4 5
EMEA-2191-SCHD-1 1 6
EMEA-2191-SCHD-1 2 7
EMEA-2191-SCHD-1 3 8
Is it possible to do it without cursor?
Thank you, Ed.
I added identity col rownum to make this records unique. Is any idea how to update result to have record number by group?
You could do this query only in Sybase IQ with analytical functions.
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc38151.1510/html/iqrefbb/BCGEEBHA.htm
I have't access to sybase IQ this time, so I can't check query, but I suppose the right query is something like
select name,
row_number() over (partition by name) as RecordNumber
from Table
AFAIK Sybase ASE has't this feature.
Update
I think you can create self join query like this
select t1.name,
t1.Rownum - t2.MinRowNum + 1
from Table as t1,
(select name, min (Rownum) as MinRowNum from Table group by name) as t2
where t1.name = t2.name
order by t1.name, t1.Rownum