I have below table -
ID | Type | Val0 | Val1 | Group | Creation_date
1 | A | V1 | Val1 | G1 | 24sep, 2011
2 | A | V1 | Val2 | G1 | 27oct, 2008
3 | A | V2 | Val3 | G2 | 19oct, 2003
4 | B | X1 | Xal1 | G3 | 15 dec, 2001
5 | B | X2 | Xal2 | G4 | 15 dec, 2000
6 | B | X2 | Xal3 | G4 | 15 dec, 1990
7 | C | X3 | Xal4 | G5 | 23Dec, 2001
I want to keep only the latest values for a particular type and extract out values which are old but not belong to group with which the latest item is associated. So, for above table, I want these items to be extracted out - Val3, Xal2, Xal3 which i can delete later.
since A is having the latest value as Val1 which belongs to group G1, B is having the latest value as Xal1 and C is having the latest value as Xal4.
Can anybody suggest me how i can do this using SQL?
You can use row_number(). No aggregation is necessary:
select t.*
from (select t.*,
row_number() over (partition by t.type order by creation_date desc) as seqnum
from t
) t
where seqnum = 1;
However, you want the values that are not in this group. That is, you want the values from val1 where seqnum is not 1. This would be:
select t.val1
from (select t.*, min(seqnum) over (partition by t.type, t.group) as min_seqnum -- DON'T USE group FOR COLUMN NAMES!
from (select t.*,
row_number() over (partition by t.type order by creation_date desc) as seqnum
from t
) t
) t
where min_seqnum <> 1;
You can use ROW_NUMBER() :
SELECT p.type,p.val1 FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.type ORDER BY t.max_d DESC) as rnk
FROM (SELECT s.Type,s.Val1,MAX(s.creation_date) as max_d
FROM YourTable s
GROUP BY s.type,s.val1) t) p
WHERE p.rnk > 1
Related
I'm trying to select from a table that essentially is a hierarchy of groups and fields in each group. Each row has a group id column and I'm trying to flatten it into rows of each group id and their fields.
For example
group id | field1
1 | a
1 | b
1 | a
1 | b
2 | c
2 | d
2 | c
2 | d
3 | e
3 | f
3 | g
3 | e
3 | f
3 | g
4 | h
It is guaranteed that a group will map to the same fields values so group 1 will always have the same number of rows with field 'a' as with field 'b'.
The target is this:
group id | field1 | field2 | field 3
1 | a | b | null
2 | c | d | null
3 | e | f | g
4 | h | null | null
I have been playing with over (order by group id) but I haven't made any progress with that or pivots either.
I wouldn't use pivot. I would use conditional aggregation and dense_rank():
select group_id,
max(case when seqnum = 1 then field1 end) as field1,
max(case when seqnum = 2 then field1 end) as field2,
max(case when seqnum = 3 then field1 end) as field3
from (select t.*,
dense_rank() over (partition by group_id order by field1) as seqnum
from t
) t
group by group_id
Not sure this will solve your problem. If you are generating any report then you can use LISTAGG function.
select listagg( field_1 , ',') within group (order by group_id)
from (
select distinct group_id, field_1 from table
);
I working on a query for SQL Server 2016. I have order by serial_no and group by pay_type and I would like to add row number same example below
row_no | pay_type | serial_no
1 | A | 4000118445
2 | A | 4000118458
3 | A | 4000118461
4 | A | 4000118473
5 | A | 4000118486
1 | B | 4000118499
2 | B | 4000118506
3 | B | 4000118519
4 | B | 4000118521
1 | A | 4000118534
2 | A | 4000118547
3 | A | 4000118550
1 | B | 4000118562
2 | B | 4000118565
3 | B | 4000118570
4 | B | 4000118572
Help me please..
SELECT
ROW_NUMBER() OVER(PARTITION BY paytype ORDER BY serial_no) as row_no,
paytype, serial_no
FROM table
ORDER BY serial_no
You can assign groups to adjacent pay types that are the same and then use row_number(). For this purpose, the difference of row numbers is a good way to determine the groups:
select row_number() over (partition by pay_type, seqnum - seqnum_2 order by serial_no) as row_no,
t.*
from (select t.*,
row_number() over (order by serial_no) as seqnum,
row_number() over (partition by pay_type order by serial_no) as seqnum_2
from t
) t;
This type of problem is one example of a gaps-and-islands problem. Why does the difference of row numbers work? I find that the simplest way to understand is to look at the results of the subquery.
Here is a db<>fiddle.
add this to your select list
ROW_NUMBER() OVER ( ORDER BY (SELECT 1) )
since you already sorting by your stuff, so you don't need to sorting in your windowing function so consuming less CPU,
Given the following example table:
+-----------+
| Id | Name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | B |
| 4 | C |
| 5 | A |
| 6 | B |
| 7 | B |
| 8 | B |
| 9 | B |
| 10 | X |
+----+------+
I would like a query to get the following result:
+----+------+
| 6 | B |
| 7 | B |
| 8 | B |
| 9 | B |
+----+------+
The best query I could do was:
SELECT * FROM
(SELECT id, name, LEAD(id) OVER (ORDER BY id) t
FROM test WHERE name = 'B' ORDER BY id)
WHERE ID <> t-1;
sqlfiddle here
If you want the length and where it starts:
select min(id), max(id)
from (select t.*,
row_number() over (order by id) as seqnum,
row_number() over (partition by name order by id) as seqnum_1
from test t
) t
where name = 'B'
group by (seqnum - seqnum_1)
order by min(id) desc
fetch first 1 row only;
You can join back to the table to get the original rows.
Another method using window functions to count the number of non-Bs after a given row . . . and then choose the first:
select t.*
from (select t.*,
dense_rank() over (order by nonbs_after asc) as grp
from (select t.*,
sum(case when name <> 'B' then 1 else 0 end) over (order by id desc) as nonbs_after
from test t
) t
where name = 'B'
) t
where grp = 1;
Here is a db<>fiddle.
My table looks like this, what I'm trying to achieve is to pull out all the records for one user for the product that have the earliest date
product |type_id| user | Date |Desired ROW_NUMBER as output |
-------+--------+------+-------+---------------------
1 | 1 | A | 0101 | 1
1 | 1 | A | 0102 | 1
2 | 3 | A | 0105 | 2
2 | 5 | A | 0105 | 2
3 | 7 | B | 0101 | 1
3 | 8 | B | 0104 | 1
So I want to pull all the records with "1" in the desired row_num column, but I haven't figured out hot to get this without doing another group by. Any helps would be appreciated.
You can use window functions:
select t.*
from (select t.*,
rank() over (partition by user order by min_date) as seqnum
from (select t.*,
min(date) over (partition by user, product) as min_date
from t
) t
) t
where seqnum = 1;
Or, with only one subquery:
select t.*
from (select t.*,
min(date) over (partition by user, product) as min_date_up,
min(date) over (partition by user) as min_date_u
from t
) t
where min_date_u = min_date_up;
You can interpret this as "return all rows where the product has the minimum date for the user".
Here is a db<>fiddle.
SELECT * FROM [tableName] WHERE Desired ROW_NUMBER = 1 ORDER BY Date[DESC, ASC]
Pass the Desired ROW_NUMBER value dynamically as a parameter.
I have a data like
id1,apple,0
id2,orange,0
id3,banana,0
id4,carrot,0
ida,kiwi,1
idb,potato,1
idc,cakes,1
idd,chocos,1
I need to shuffle on the base of last column (0 THEN 1) like
id1,apple,0
ida,kiwi,1
id2,orange,0
idb,potato,1
id3,banana,0
idc,cakes,1
id4,carrot,0
idd,chocos,1
Is that possible in sqlite or in notepad++ ??
If the version of SQLite you use supports it you can do it with row_number() window function:
select t.id, t.fruit, t.number
from (
select *,
row_number() over (partition by number order by id) rn
from tablename
) t
order by t.rn
If you need the rows shuffled, replace order by id with order by random().
See the demo.
If you can't use window functions:
select t.id, t.fruit, t.number
from (
select t.*,
(select count(*) from tablename where number = t.number and id < t.id) rn
from tablename t
) t
order by t.rn
See the demo.
Results:
| id | fruit | number |
| --- | ------ | ------ |
| id1 | apple | 0 |
| ida | kiwi | 1 |
| id2 | orange | 0 |
| idb | potato | 1 |
| id3 | banana | 0 |
| idc | cakes | 1 |
| id4 | carrot | 0 |
| idd | chocos | 1 |
You can do this using row_number() in the order by clause:
select t.*
from t
order by row_number() over (partition by col3 order by col1),
col1;
Often "shuffle" implies randomness ("interleaving" would not). If that is what you mean:
select t.*
from t
order by row_number() over (partition by col3 order by random()),
col1