Postgres SQL to extract rows based on sequence number - sql

I have data in Telephone table, something as below:
ID
area
exch
line
ext
tel_type_cde
tel_seq_num
modified_dttm
1234
482
876
789
1234
0
0
01-01-2023
1234
483
877
123
0
1
01-02-2023
1234
123
234
456
1234
1
0
01-01-2023
1235
483
877
456
0
1
01-01-2023
1236
483
877
123
0
0
01-02-2023
1236
123
234
456
1234
0
1
01-02-2023
1236
483
877
458
0
2
01-03-2023
For an ID/tel_type_cde combination there might be multiple rows and telephone sequence number is used to derive from latest number which needs to considered further
Expected output
ID
area
exch
line
ext
tel_type_cde
1234
483
877
123
0
1234
123
234
456
1234
1
1235
483
877
456
0
1236
483
877
458
0
Drafted below query so far, but not working as expected
select distinct on (ID)
ID,
area,
exch,
line,
ext,
tel_type_cde
from telephone
order by ID,tel_seq_num desc;
Appreciate any help!

try this :
SELECT DISTINCT ON (id, tel_type_cde)
id, area, exch, line, ext, tel_type_cde
FROM telephone
ORDER BY id, tel_type_cde, tel_seq_num DESC ;

You can use the RANK window function with a common table expression to get the expected results
WITH cte AS (
SELECT ID, area, exch, line, ext, tel_type_cde, RANK() OVER (PARTITION BY id, tel_type_cde ORDER BY tel_seq_num DESC) as r
FROM telephone
)
SELECT
ID, area, exch, line, ext, tel_type_cde
FROM cte
WHERE r = 1;
Fiddle

Related

How find duplicates of the same id but different date with SQL (Oracle)

I've got a datatable like that :
id
line
datedt
123
1
01/01/2021
123
2
01/01/2021
123
3
01/01/2021
777
1
13/04/2020
777
2
13/04/2020
123
1
12/04/2021
123
2
12/04/2021
888
1
01/07/2020
888
2
01/07/2020
452
1
05/01/2020
888
1
02/05/2021
888
2
02/05/2021
I'd like to obtain a result like that, ie : the nb of same id with differents dates.
Example we can find 123 with 2 diffents dates, 888 too, but only date for 777 and 452
id
nb
123
2
777
1
888
2
452
1
How could I get that ?
Hope it's clear :)
Thanks you
select id , count(distinct datedt) as nb
from table
group by id

Break values in one column into multiple rows

I am trying to explode values belonging to one id into multiple rows.
category_id subcategory_ids
123 111
123
333
465 444
555
The result I am trying to achieve should look like below-
category_id subcategory_ids
123 111
123 123
123 333
465 444
465 555
Below is for BigQuery Standard SQL
#standardSQL
SELECT category_id, subcategory_ids
FROM `project.dataset.table`,
UNNEST(subcategory_ids) subcategory_ids

SQL Server: LAG() OVER (ORDER BY Y) apply same result for duplicate Y value

When I use
LAG(Static_Col_2, 1) OVER (ORDER BY Static_Col_1) AS LAGged_Col
I get these results:
Static_Col_1 Static_Col_2 LAGged_Col
----------------------------------------
1 456 NULL
2 457 456
3 458 457
4 459 458
5 460 459
5 461 460
5 462 461
But I want:
Static_Col_1 Static_Col_2 LAGged_Col
----------------------------------------
1 456 NULL
2 457 456
3 458 457
4 459 458
5 460 459
5 461 459
5 462 459
When '5' repeats the LAG should point to '4' every time.
I don't think you can do this in SQL Server with a simple window function. You can nest window functions or use a group by/join:
select t.*, tt.prev_col2
from t join
(select col1, lag(max(col2)) over (order by col1) as prev_col2
from t
group by col1
) tt
on t.col1 = tt.col1
order by 1;
Here is a db<>fiddle.

Redshift SQL query help needed

Table order_details:
order_id dish_id category_id
----------------------------------
601 22 123
601 23 234
603 32 456
603 54 456
603 11 543
603 19 456
From the sample table provided above: how can I group the order_id,dish_id and category_id on the basis of distinct group with respect to each order_id?
The result should look like
order_id dish_id category_id count
---------------------------------------------
601 22 123 1
601 23 234 1
603 32 456 3
603 54 452 3
603 11 543 3
603 19 456 3
Note:
Like dish_id 22 in order_id 601 went along with 1 different distinct category_id i.e 234, and similarly in order_id 603 dish_id 32 went along 2 different distinct category_id ie 456, 543
If I assume that the triplets are unique, you seem to want 1 less than the count of the group. That would be:
select t.*,
(count(*) over (partition by order_id) - 1) as cnt
from t;

Using sequences to create group ID

I'm attempting to create group_ids based on a set of item_ids. The only indication that the item_ids are part of a single group is the fact that item_ids are sequential. For example, based on the first two columns below, the output I want is the third:
item item_id group_id
ABC 282 2
ABC 283 2
ABC 284 2
ABC 285 2
ABC 051 3
ABC 052 3
ABC 189 4
ABC 231 5
ABC 232 5
ABC 233 5
ABC 234 5
ABC 247 6
ABC 248 6
ABC 249 6
ABC 250 6
ABC 091 7
ABC 092 7
The group_id doesn't necessarily have to be sequential itself, it only has to be unique. I attempted this with the following code:
create sequence seq
start with 1
minvalue 1
increment by 1
cache 20;
select seq.nextval from dual; --to initialize the sequence
select
item,
item_id,
case when diff = 1 then seq.currval else seq.nextval end group_id
from
(
select
item,
item_id,
(id - lag(id, 1, 0) over (order by 1) diff
from
(
select
item,
item_id
from
table
)
);
But get the following output:
item item_id group_id
ABC 282 2
ABC 283 3
ABC 284 4
ABC 285 5
ABC 051 6
ABC 052 7
ABC 189 8
ABC 231 9
ABC 232 10
ABC 233 11
ABC 234 12
ABC 247 13
ABC 248 14
ABC 249 15
ABC 250 16
ABC 091 17
ABC 092 18
When looking for the cause of the problem, I found an excellent explanation by user ShannonSeverance that details why my solution won't work. However, it didn't provide any suggestions on how to move forward.
Does anyone have any ideas?
You have a problem, because SQL tables are inherently unordered. The following "should" logically work, although it won't in practice:
select ii.*, (item_id - rownum) as grp_id
from item_ids ii;
A sequence of item_ids in order minus the row number is constant. You can use that for a group, at least for a given item. To handle multiple items, concatenate the values together:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii;
To really make this work, you need to add an order by -- this guarantees the ordering of the results from the select. This might work, assuming that there are "holes" between the groups:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii
order by item, item_id;
Otherwise, you need some other column to determine the proper ordering for the items.