SQL to find related rows in Loop in ANSI SQL or Snowflake SQL - sql

I have a requirement where I need to link all related CUSTOMER ID and assign a Unified Cust ID to all the related Cust_id.
Ex: for below data,
INPUT DATA
PK_ID CUST_ID_1 CUST_ID_2 CUST_ID_3
1 123 456 567
2 898 567 780
3 999 780 111
4 111 222 333
Based on CUST_ID_1/CUST_ID_2/CUST_ID_3 need to link all the and assign a Unified ID to all the rows.
OUTPUT DATA
Unified ID CUST_ID_1 CUST_ID_2 CUST_ID_3
1000 123 456 567
1000 898 567 780
1000 999 780 111
1000 111 222 333
Trying to perform Self Join but it cannot be definite. Is there a function or ANSI SQL feature which can help in this?
What i have tried,
CREATE TEMP TBL_TEMP AS(
SELECT A.PK_ID
FROM TBL A
LEFT JOIN TBL B
ON A.CUST_ID_1=B.CUST_ID_1
AND A.PK_ID<>B.PK_ID)
UPDATE TBL
FROM TBL_TEMP
SET UNIFIED_ID=SEQ_UNIF_ID.nextval
WHERE TBL.PK_ID=TBL_TEMP.PK_ID
This update i have to write for each column and multiple times.

If you are ok with gap in sequences then following is what I can come up with as of now.
update cust_temp a
set unified_id = t.unified_id
from
(
select
case
when (select count(*) from cust_temp b
where arrays_overlap(array_construct(a.cust_id_1,a.cust_id_2,a.cust_id_3),
array_construct(b.cust_id_1,b.cust_id_2,b.cust_id_3)))>1 -- match across data-set
then 1000 -- same value for common rows
else
ts.nextval --- using sequence for non-common rows
end unified_id,
a.cust_id_1,a.cust_id_2,a.cust_id_3
from cust_temp a, table(getnextval(SEQ_UNIF_ID)) ts) t
where t.cust_id_1 = a.cust_id_1
and t.cust_id_2 = a.cust_id_2
and t.cust_id_3 = a.cust_id_3;
Updated data-set
select * from cust_temp;
UNIFIED_ID
CUST_ID_1
CUST_ID_2
CUST_ID_3
1000
123
456
567
1000
898
567
780
1000
111
222
333
20000
100
200
300
1000
999
780
111
1000
234
123
901
23000
260
360
460
24000
160
560
760
Original data set -
select * from cust_temp;
UNIFIED_ID
CUST_ID_1
CUST_ID_2
CUST_ID_3
NULL
123
456
567
NULL
898
567
780
NULL
111
222
333
NULL
100
200
300
NULL
999
780
111
NULL
234
123
901
NULL
260
360
460
NULL
160
560
760
Arrays_overlap logic is thanks to #Simeon.
Following procedure can be used -
EXECUTE IMMEDIATE $$
DECLARE
duplicate number;
x number;
BEGIN
duplicate := (select count(cnt) from (select a.unified_id,count(*) cnt from cust_temp a,
cust_temp b
where
arrays_overlap(array_construct(a.cust_id_1,a.cust_id_2,a.cust_id_3),
array_construct(b.cust_id_1,b.cust_id_2,b.cust_id_3))
AND a.cust_id_1 != b.cust_id_1
AND a.cust_id_2 != b.cust_id_2
AND a.cust_id_3 != b.cust_id_3
group by a.unified_id) where cnt>1
);
for x in 1 to duplicate do
update cust_temp a
set a.unified_id = (select min(b.unified_id) uid from cust_temp b
where arrays_overlap(array_construct(a.cust_id_1,a.cust_id_2,a.cust_id_3),
array_construct(b.cust_id_1,b.cust_id_2,b.cust_id_3)));
end for;
END;
$$
;
Which will produce following output dataset -
UNIFIED_ID
CUST_ID_1
CUST_ID_2
CUST_ID_3
1000
100
200
300
2000
123
456
567
2000
898
567
780
2000
111
222
333
2000
999
780
111
2000
234
123
901
7000
260
360
460
8000
160
560
760
8000
186
160
766
For an input data-set as -
UNIFIED_ID
CUST_ID_1
CUST_ID_2
CUST_ID_3
1000
100
200
300
2000
123
456
567
3000
898
567
780
4000
111
222
333
5000
999
780
111
6000
234
123
901
7000
260
360
460
8000
160
560
760
9000
186
160
766

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

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;

SQL server 2012 - Oder by Debit, Credit

I have a table data like this:
TranNo Acc No Bal Acc Debit Credit
1 511 131 1000
1 521 131 200
1 333 131 80
1 131 511 1000
1 131 521 200
1 131 333 80
Is there a way to select data and order like this? I'm using SQL Server 2012. Thank you!
TranNo Acc No Bal Acc Debit Credit
1 131 511 1000
1 511 131 1000
1 521 131 200
1 131 521 200
1 131 333 80
1 333 131 80
I think so. I think that ordering by the least and greatest of the accounts gets the pairs that you want. Then, additional logic gets the debit before the credit:
select t.*
from table t
order by (case when accno < balacc then accno else balacc end),
(case when accno < balacc then balacc else accno end),
(case when debit > 0 then 1 else 0 end);

Retrieving data from unnormalized vertically ordered table

I have the following relation:
employeevalue(id, name, value, code)
id name value code
101 bobby 150 100
101 bobby 12 150
101 bobby 14.6 200
102 mary 189 100
102 mary 128 150
102 mary 112 200
103 john 112 100
103 john 13 150
103 john 76 200
Where code 100 is value1, 150 is value2 and 200 is value3. How could I write an SQL statement to retrieve the following from this table?
id name value1 value2 value3
101 bobby 150 12 14.6
102 mary 189 128 112
103 john 112 13 76
You can do this with conditional aggregation:
select id,
max(case when code = 100 then value end) as value1,
max(case when code = 150 then value end) as value2,
max(case when code = 200 then value end) as value3
from table t
group by id;

How will i join/combine these two table to get one result

Table 1
Code Name1 type BalanceDue id1 id2 id3 id4 id5 emp
2600 intl-Airfare 1 2.38 120 410 510 603 7060513 null
1100 intl-travel 1 2.66 120 420 540 602 7060513 null
2400 intl-Meals 1 1.50 120 420 520 602 7060513 null
4100 Transpo 2 19.70 110 210 510 601 null
4100 Transpo 2 13.25 110 210 500 601 null
4100 Transpo 2 17.38 110 210 500 600 null
3600 Dom travel 3 25.11 110 210 500 600 55713 null
Table 2
Code Details Total type code1 code2 code3 code4 code5 emp
4100 no#233 Emp1-Parking 11.39 2 110 210 510 601 null null
4100 no#231 Jes-Parking 6.83 2 110 210 510 601 null null
4100 no#232 Jes-TransExp 1.48 2 110 210 510 601 null null
4100 no#234 Emp2-TollFee 0.23 2 110 210 500 601 null null
4100 no#239 Emp2-Parking 1.82 2 110 210 500 601 null null
4100 no#240 Emp3-Parking 2.96 2 110 210 500 601 null null
4100 no#252 Emp5-TollFee 8.24 2 110 210 500 601 null null
4100 no#235 Jay-TollFee 4.90 2 110 210 500 600 null null
4100 no#243 Jay-TransExp 12.48 2 110 210 500 600 null null
I want this as a result:
if type is 1 then display all values in table 1 which has type 1
same as if type is 3
if type is 2 then display all values in table 2 considering code1 to code5
Result
Code Details type Total code1 code2 code3 code4 code5 emp
2600 intl-Airfare 1 2.38 120 410 510 603 7060513 null
1100 intl-travel 1 2.66 120 420 540 602 7060513 null
2400 intl-Meals 1 1.50 120 420 520 602 7060513 null
4100 no#233 Emp1-Parking 2 11.39 110 210 510 601 null null
4100 no#231 Jes-Parking 2 6.83 110 210 510 601 null null
4100 no#232 Jes-TransExp 2 1.48 110 210 510 601 null null
4100 no#234 Emp2-TollFee 2 0.23 110 210 500 601 null null
4100 no#239 Emp2-Parking 2 1.82 110 210 500 601 null null
4100 no#240 Emp3-Parking 2 2.96 110 210 500 601 null null
4100 no#252 Emp5-TollFee 2 8.24 110 210 500 601 null null
4100 no#235 Jay-TollFee 2 4.90 110 210 500 600 null null
4100 no#243 Jay-TransExp 2 12.48 110 210 500 600 null null
3600 Dom travel 3 25.11 110 210 500 600 55713 null
Sometimes, id5 has a value and sometimes other columns were null.
sorry, i hope i explained it clearly :(
Thanks everyone!
Your desired results look like a UNION (The UNION clause lets your "merge" together more queries in a single, final result set) similar to this:
SELECT Code, Name1 as Details, type, BalanceDue as Total,id1 as code1, id2 as code2,
id3 as code3, id4 as code4, id5 as code5, emp
FROM Table1 WHERE type IN (1, 3) -- could also be WHERE type = 1 OR type = 3
UNION
SELECT Code, Details, type, Total, code1, code2, code3, code4, code5, emp
FROM Table2 WHERE type = 2