Oracle 11g - Creating a side by side comparison of table comlumn data - sql

I have a query where I need to extract data in a regular table and put two rows of data into a single row.
I have rows that consist of
StudentID AUDIT_ACTN Audit_Date .....
aaa A 01/01/2010
aaa A 03/04/2011
aaa A 02/02/2013
aaa D 09/10/2010
aaa D 05/06/2011
aaa D 06/07/2013
aaa A 11/12/2014~
bbb A 01/01/2010
bbb A 03/04/2011
bbb A 02/02/2013
bbb D 09/10/2010
bbb D 05/06/2011
bbb D 06/07/2013
bbb A 11/12/2014~
I want output like this
StudentID AUDIT_ACTN Audit_Date StudentID AUDIT_ACTN Audit_Date
aaa A 01/01/2010 aaa D 09/10/2010
aaa A 03/04/2011 aaa D 05/06/2011
aaa A 02/02/2013 aaa D 06/07/2013
aaa A 11/12/2014 NULL NULL NULL
bbb A 01/01/2010 bbb D 09/10/2010
bbb A 03/04/2011 bbb D 05/06/2011
bbb A 02/02/2013 bbb D 06/07/2013
bbb A 11/12/2014 NULL NULL NULL
The A & D data rows are related, a= add the something to the record and d = delete something from the record (something is an indicator). These is logical in that you must add something before you delete it and you cannot add it twice, without deleting it first.
My current script is probably going down the wrong track but here goes;
select a.StudentId,a.Audit_Date,a.AUDIT_ACTN,d.StudentId,Audit_Date,d.AUDIT_ACTN,
from table a
join
(select *
from
(Select StudentId, Audit_Date,AUDIT_ACTN
from table b
Where b.AUDIT_ACTN='D'
order by Audit_Date
)
where rownum=1
) d on a.StudentId = d.StudentId
and a.AUDIT_ACTN='A'
and Select * from (Select Audit_Date
Order by a.StudentId, a.Audit_Date
I know this is wrong but where do I go from here. If anyone can help and point me in the right direction. It would be appreciated.
My current attempts bring me zero rows, when I take out the rownum it brings me a x join returning 12 rows in this case.
thanks
Roger

I think you need aggregate function like below
select
A.StudentId,A.Audit_Date,A.AUDIT_ACTN,
D.StudentId,D.Audit_Date,D.AUDIT_ACTN
from
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='D'
) D
FULL OUTER JOIN
(Select StudentId, Audit_Date,AUDIT_ACTN,ROW_NUMBER()
OVER (PARTITION BY StudentId order by audit_date) rn
from table b
Where b.AUDIT_ACTN='A'
) A
on A.rn = D.rn and A.StudentId = B.StudentId
I hope this will work

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

oracle sub query or union

I have a case table as follows:
caseId
caseType
last_name
first_Name
aCaseStatus
bCaseStatus
created_by
1
P
test
a
0
0
1
2
M
test1
b
1
2
2
3
M
test2
c
1
3
1
aCaseStatus
id
descr
1
aaa
2
bbb
3
ccc
bCaseStatus
id
descr
1
xxx
2
yyy
3
zzz
I have a query like below
select c.case_id caseId, c.last_name lastName, c.first_name firstName,
caseType caseType,
acaseStatus||','||bCaseStatus as caseStatus
from cases c
join aCaseStatus acs
on acs.id = c.aCaseStatus
left outer join bCaseStatus bcs
on bcs.id = c.bCaseStatus
where (c.created_by = 1 ) and ( c.aCaseStatus in (1) or c.bCaseStatus in (0)) and c.caseType='M'
UI has a display like below
caseId
Name
caseStatus
2
b,test1
aaa, yyy
3
c,test2
aaa, zzz
When you look at the UI display caseStatus is a combination of aCaseStatus, bCaseStatus.
Also, the UI table has a search functionality wherein caseStatus is a multi-select dropdown field.
This dropdown has a combination of aCaseStatus and bCaseStatus.
Dropdown is as below:
CaseStatus
aaa
bbb
ccc
xxx
yyy
zzz
Note: aCaseStatus alone is a mandatory field so I have given an inner join, however, bCaseStatus is not so I have given a left outer join.
When the user selects aaa, UI should display:
caseId
Name
caseStatus
2
b,test1
aaa
3
c,test2
aaa
when the user selects aaa, xxx UI should display:
caseId
Name
caseStatus
2
b,test1
aaa, xxx
3
c,test2
aaa
But when I use the above query for aaa selection I get:
caseId
Name
caseStatus
2
b,test1
aaa, xxx
3
c,test2
aaa
I do not want the xxx to be displayed even though caseId has xxx caseStatus. How should I change the query to achieve this? Should I write a union query one for aCaseStatus and the other for bCaseStatus or is there any other way this can be achieved?
Suggestions, please?

combine three tables in oracle sql

I'm having these three tables
Table A:
code aname
----------- ----------
1 A
2 B
3 C
Table B:
code bname
----------- ----------
1 aaa
1 bbb
2 ccc
2 ddd
Table C
code cname
----------- ----------
1 xxx
1 yyy
1 zzz
2 www
How can I achieve the output like this using single query ?
code aname bname cname
----------- ---------- ---------- ----------
1 A aaa xxx
1 A bbb yyy
1 A NULL zzz
2 B ccc www
2 B ddd NULL
3 C NULL NULL
Any suggestions ?
Thanks
It looks like you want "lists" to be vertical for tables B and C. This is doable, by using row_number(). However, the trick is getting the third row in where there are no matches.
Here is one method. It uses a full outer join to combine the b and c names together. It then uses left join to bring in the a records.
select a.code, a.name, bc.bname, bc.cname
from a left join
(select coalesce(b.code, c.code) as code, bname, cname
from (select code, bname, NULL as cname,
row_number() over (partition by code order by code) as seqnum
from b
) b full outer join
(select code, NULL as bname, cname,
row_number() over (partition by code order by code) as seqnum
from c
) c
on b.code = c.code and b.seqnum = c.seqnum
) bc
on bc.code = a.code;

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.

Append tables in SQL

If I have the two following tables,
Table1
ItemNo Desc Order Number Qty S_Date Location
AA AA AAA A AA/AA/AAAA AAAA
BB BB BBB B BB/BB/BBBB BBBB
CC CC CCC C CC/CC/CCCC CCCC
Table 2
M_Order Item M_Date Total
XXX X XX/XX/XXXX XX
YYY Y YY/YY/YYYY YY
Can anyone advice me how to get the following table please.
Result Table
ItemNo Desc Order Number Qty S_Date Location M_Date Total
AA AA AAA A AA/AA/AAAA AAAA
BB BB BBB B BB/BB/BBBB BBBB
CC CC CCC C CC/CC/CCCC CCCC
X XXX XX/XX/XXXX XX
Y YYY YY/YY/YYYY YY
Thanks
You can do this with a full outer join trick:
select t1.*, t2.*
from table1 t1 full outer join
table2 t2
on 1 = 0;
This will give you the columns in both tables. Each row will be populated with values from only one of the tables.
Similar to Gordons answer but the use of stars in SQL is one of the biggest NO NO's there is.
Also for the actual join part itself you need to do tablename.column = tablename.column on the unique columns. 1 = 0 is a bit ambiguous. but you get the picture
Use the below query join those two tables.
I think you wish to combine the values of two [(ItemNo and Item) and (Desc and M_Desc)] columns in same column and all the other columns separately.
SELECT CAST(ItemNo AS VARCHAR(MAX)) AS ItemNo, CAST(Desc AS VARCHAR(MAX)) AS Desc, OrderNumber, Qty,
S_Date, Location, NULL AS M_Date, NULL AS Total
FROM Table1
UNION ALL
SELECT CAST(Item AS VARCHAR(MAX)) AS ItemNo, CAST(M_Order AS VARCHAR(MAX)) AS Desc, NULL AS OrderNumber, NULL AS Qty,
NULL AS S_Date, NULL AS Location, M_Date, Total
FROM Table2