multiple result Rows in one row - sql

I have this kind of result from a Select like this
Select a.Header1, a.Header2, a.Header3, b.header4,
From a
Join b on a.id = b.id
give this result
Head1 Head2 Head3 Head4
1 A 1 AA
1 A 1 BB
1 A 1 CC
1 A 2 AA
1 A 2 CC
1 A 2 DD
1 A 2 EE
Is it possible to have
Head1 Head2 Head3 Head4
1 A 1 AA BB CC
1 A 2 AA CC DD EE
Head4 being split in different columns

Not exactly. You can use the listagg() function to concatenate the values into a single column which you can then split after the fact. Example:
SELECT
a.Header1,
a.Header2,
a.Header3,
listagg(b.Header4, ', ') WITHIN GROUP (ORDER BY b.Header4) AS Header4
FROM a
JOIN b ON a.id = b.id
GROUP BY
a.Header1,
a.Header2,
a.Header3
Would yield:
Header1 Header2 Header3 Header4
1 A 1 AA, BB, CC
1 A 2 AA, CC, DD, EE

Related

How to make LEFT JOIN to rows having max date in BQ?

I have 2 tables in Big Query:
TABLE A
ID
Name
Date_A
field_x
field_y
field_z
xxx
tata
10/11/2021
a
0
1
xxx
tata
11/11/2021
a
1
1
zzz
tutu
01/11/2021
b
0
1
zzz
tutu
05/11/2021
b
1
1
yyy
titi
02/11/2021
c
0
1
uuu
tata
08/11/2021
d
0
0
TABLE B
ID
Name
Date_B
field_A
field_B
xxx
tata
13/11/2021
AA
BB
zzz
tutu
01/11/2021
CC
DD
yyy
titi
11/11/2021
AA
BB
uuu
tata
05/11/2021
DD
DD
And I would like to link (left join on ID and Name) rows from table B to the max date of table A, to get :
ID
Name
Date_A
field_x
field_y
field_z
field_A
field_B
xxx
tata
10/11/2021
a
0
1
NULL
NULL
xxx
tata
11/11/2021
a
1
1
AA
BB
zzz
tutu
01/11/2021
b
0
1
NULL
NULL
zzz
tutu
05/11/2021
b
1
1
CC
DD
yyy
titi
02/11/2021
c
0
1
AA
BB
uuu
tata
08/11/2021
d
0
0
DD
DD
How can I do that in SQL (Big Query) please ? Thanks
Consider below approach
select a.*,
(if(row_number() over win = 1, b, null)).* except(id, name, date_b)
from table_a a
left join table_b b
using(id, name)
window win as (partition by a.id, a.name order by date_a desc)
if applied to sample data in your question - output is
I didn't tested it but I think you should left join the b table to a table in which the max date is indicated. Usage of condition pure on the left table is somewhat unusual though from the definition of left join I expect it to work.
select a_ranked.ID, a_ranked.Name, a_ranked.Date_A
, a_ranked.field_x, a_ranked.field_y, a_ranked.field_z
, b.field_A, b.field_B
from (
select a.*, rank() over (partition by ID, Name order by Date_A desc) as r
from a
) a_ranked
left join b on a_ranked.ID = b.ID and a_ranked.Name = b.Name and a_ranked.r = 1

How to skip n rows for order by clause in SQL Server

I have a dataset. The first 2 rows should be ignored and ordering (by name column) should start from the 3rd row. And it should be done through a query only.
aaa g 900
zzz g 900 -- the first 2 rows should be fixed
bb g 900 -- ordering should start from here
yy g 900
rrr g 900
fff g 900
Desired output:
aaa g 900
zzz g 900
bb g 900
ff g 900
rrr g 900
yy g 900
You can use case logic in the order by:
order by (case when col1 = 'aaa' then 1
when col1 = 'zzz' then 2
else 3
end),
col1
select *
from table_name
except
select top 2 *
from table_name
order by column_name

Update rows from other rows

how can i update this table (zz col):
id xx yy zz n
---- ----- ----- --- -----
1 AA 20 0 0
2 AA 10 0 1
3 AA 10 0 2
4 BB 45 0 0
5 BB 15 0 1
6 BB 15 0 2
7 BB 15 0 3
[zz = yy where n = 0]
To:
id xx yy zz n
---- ----- ----- --- -----
1 AA 20 20 0
2 AA 10 20 1
3 AA 10 20 2
4 BB 45 45 0
5 BB 15 45 1
6 BB 15 45 2
7 BB 15 45 3
Thanks
update tablename set zz=yy where n=0;
You can join on the same table to do your update.
UPDATE A1
SET A1.zz = A2.yy
from
A AS A1
inner join A AS A2 ON A1.xx = A2.xx AND A2.n = 0
You may need to try this way (not tested, but this should help you)
Your UPDATE statement needs to be a correlated update-- you need some key in A that tells you which row in B to go to in order to retrieve the new value. Your WHERE clause should also be an IN or an EXISTS since it needs to return multiple rows.
UPDATE table1 a
SET a.zz = (SELECT b.yy
FROM table1 b
WHERE b.n = 0
AND a.id = b.id)
WHERE EXISTS (SELECT 1
FROM table1 b
WHERE a.id = b.id);
Assuming the join results in a key-preserved view, you could also
UPDATE (SELECT a.id,
a.yy oldval,
x.yy newval
FROM table1 a,
(SELECT b.id,
b.xx,
b.yy
FROM table1 b
WHERE b.n = 0) x
WHERE a.xx = x.xx)
SET oldval = newval;
Try this query
update tablename
set a.zz=(select a.yy
from tablename a
where a.xx=tablename.xx and a.n=0)
you can try this:
UPDATE table1
SET table1.zz= table2.xx
FROM table2
JOIN table1
ON table1.id=table2.id

Select only complete groups in SQL?

Suppose there are 2 tables as shown below. Table A contains rows in a few groups - 11 (1,2,3) and 22 (4,5,6,7) in this case. Table B contains book rows that indirectly reference groups in table A via B.a_id = A.a_id foreign key relationship):
Table A:
a_id grp
---------
1 11
2 11
3 11
4 22
5 22
6 22
7 22
Table B:
b_id a_id book
--------------
1 1 AA
2 2 AA
3 3 AA
4 1 BB
5 2 BB
6 3 BB
7 1 CC
8 3 CC
9 4 AA
10 5 AA
11 6 AA
12 4 BB
13 5 BB
14 6 BB
15 7 BB
16 6 CC
17 7 CC
I need to select only those book/group combinations that are complete, i.e.
a_id grp book
---------------
1 11 AA
2 11 AA
3 11 AA
1 11 BB
2 11 BB
3 11 BB
4 22 BB
5 22 BB
6 22 BB
7 22 BB
11 CC, 22 AA or 22 CC are not eligible, as they do not represent complete groups.
One way to get the desired result is to use row counts by each group in a subquery, but its seems kind of shaky. Any other ideas?
Thanks!
Edit: I don't think that the referenced question is really the same problem.
This is what I could come up with:
select
A.a_id, A.grp, B.book
from
A
inner join B
on A.a_id = B.a_id
left outer join
(select distinct A.grp, B.book
from A, B
where not exists
(
select *
from A a2
inner join B b2
on a2.a_id = b2.a_id
where
a2.a_id = A.a_id
and a2.grp = A.grp
and b2.book = B.book
)
) T1 -- < -- represents incomplete book/group combos
on A.grp = T1.grp
and B.book = T1.book
where
T1.grp is null -- < -- exclude incomplete book/group combos

how to get Unique data from one table and the other

If I want to display Order_Number data1 data2 data3 (most current by date changed OtherData1, OtherData2, OtherData3) date_changed the problem is I wasn't just one line, I was getting multiple lines for each order number.
What I would love to get is
1, a, f,q, cc,ccc,abc, 12/2/2014, bob
3, c, b,h, aa,aaa,abc, 12/2/2014, bob
Thanks!
I was working with
SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
x.date_changed, cr.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN
table2 t ON x.date_changed = t.date_changed
LEFT JOIN
table1 cr ON x.Order_Number = cr.Order_Number
WHERE cr.name = 'bob'
Here are example tables.
Table1:
Order_Number data1 data2 data3 name
1 a f q bob
2 b g g john
3 c b h bob
4 d s j john
Table2:
Order_Number date_changed OtherData1 OtherData2 OtherData3
1 11/30/2014 aa aaa abc
1 12/1/2014 bb bbb def
1 12/2/2014 cc ccc abc
3 12/1/2014 dd aaa def
2 11/30/2014 dd bbb abc
2 12/1/2014 ss ccc def
3 12/2/2014 aa aaa abc
4 11/26/2014 fc wer wsd
Your Join to config_log (Table2) needs to include the entire composite key if you want to retrieve unique rows.
JOIN
conf_log t ON x.date_changed = t.date_changed
And x.Order_Number = t.Order_number
I think you need to have 2 sub querys:
SELECT
Data.Order_Number,
Data.data1, Data.data2, Data.data3,
Data.OtherData1, Data.OtherData2, Data.OtherData3,
Data.date_changed, Data.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN (SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
t.date_changed, cr.name
FROM table2 t
JOIN table1 cr
ON t.Order_Number = cr.Order_Number) AS Data
ON x.date_changed = data.date_changed
AND x.Order_Number = data.Order_number
WHERE cr.name = 'bob'
The fact that you had cr.name in the where clause means the LEFT JOIN had the same affect as just JOIN.