Good day! I need some guidance if I want to do is actually possible in Oracle SQL.
I have a table like this:
ID
Name
Code
999
Abby
1
999
Betty
1
999
Cass
2
999
Diane
2
999
Elly
2
999
Faye
3
999
Greg
4
999
Honey
4
999
Iman
4
999
Jam
4
999
Klade
5
And I want to achieve something like this:
ID
1
2
3
4
5
999
Abby
Cass
Faye
Greg
Klade
999
Betty
Dianne
Honey
999
Elly
Iman
999
Jam
`
I have tried joins, pivots, aggregates, but nothing seems to possibly work out (as far as I tried it.)
I even tried getting all the raw data and creating a new table but the only id I can reference them with is the ID.
Please help.
Any idea or references or resource to the right direction would be appreciated!
Thanks in advance!
Pivot is one option.
select *
from (select id, name, code,
row_number() over (partition by code order by name) rn
from test
)
pivot
(listagg(name, '') within group (order by null) val
for code in (1, 2, 3, 4, 5)
);
which results in
ID RN 1_VAL 2_VAL 3_VAL 4_VAL 5_VAL
---------- ---------- ---------- ---------- ---------- ---------- ----------
999 1 Abby Cass Faye Greg Klade
999 2 Betty Diane Honey
999 3 Elly Iman
999 4 Jam
The key idea is to use row_number(), but I prefer conditional aggregation:
select code,
max(case when code = 1 then name end) as code_1,
max(case when code = 2 then name end) as code_2,
max(case when code = 3 then name end) as code_3,
max(case when code = 4 then name end) as code_4,
max(case when code = 5 then name end) as code_5
from (select t.*,
row_number() over (partition by id, code order by name) as seqnum
from t
)
group by id, seqnum
Related
I have a few tables like this where a person has multiple data rows. The IDs are sequential but do not always start at 1. Is there a way to have the results come out in a single data row for each person. I have a few tables like this and I ultimately would like to join them via CLIENT_ID, but I'm a bit stumped. Is this possible?
Using oracle sql.
CLIENT_ID
NAME
ID
ID_DESCRIPTION
5
joe
1
apple
5
joe
5
orange
68
brian
2
orange
68
brian
6
mango
68
brian
10
lemon
12
katie
3
watermelon
where the results look like this
CLIENT_ID
NAME
ID1
ID1_DESCRIPTION
ID2
ID2_DESCRIPTION
ID3
ID3_DESCRIPTION
5
joe
1
apple
5
orange
68
brian
2
orange
6
mango
10
lemon
12
katie
3
watermelon
If Pivot ist not available, this should do it:
Select
Client_id,
sum(case when id_description='apple' then 1 else 0 end) as Apples,
sum(case when id_description='orange' then 1 else 0 end) as Oranges...
[]etc.
from
t
group by Client_ID
Might need some minor tweaking as I wrote this just off the top of my head, but something like this should work. Will say this doesn't account for more than 3 rows per CLIENT_ID. For that, would need to do a dynamic pivot (plenty of online articles on this topic).
Pivoting Based on Order of Items
WITH cte_RowNum AS (
SELECT ROW_NUMBER() OVER (PARTITION BY CLIENT_ID ORDER BY ID) AS RowNum
,*
FROM YourTable
)
SELECT CLIENT_ID
,MAX(CASE WHEN RowNum = 1 THEN ID END) AS ID1
,MAX(CASE WHEN RowNum = 1 THEN [Description] END) AS ID1_DESCRIPTION
,MAX(CASE WHEN RowNum = 2 THEN ID END) AS ID2
,MAX(CASE WHEN RowNum = 2 THEN [Description] END) AS ID2_DESCRIPTION
,MAX(CASE WHEN RowNum = 3 THEN ID END) AS ID3
,MAX(CASE WHEN RowNum = 3 THEN [Description] END) AS ID3_DESCRIPTION
FROM cte_RowNum
GROUP BY CLIENT_ID;
Lets say my table contains the following data
id
name
version
1
Rahul
1
1
Rahul
2
2
John
1
3
Mike
1
2
John
2
4
Rubel
1
5
David
1
1
Rahul
3
I need to filter the duplicate records with lower version. How can this be done?
The output essentially should be
id
name
version
1
Rahul
3
2
John
2
3
Mike
1
4
Rubel
1
5
David
1
For this dataset, aggregation seems sufficient:
select id, name, max(version) as max_version
from mytable
group by id, name
You can use not exists as follows:
select id, name, version
from your_table t
Where not exists
(Select 1 from your_table tt
Where tt.id = t.id and tt.version > t.version)
Or you can use analytical function row_number as follows:
Select id, name, version from
(select t.*,
Row_number() over (partition by id order by version desc) as rn
from your_table t) t
Where rn = 1
can we get the below desired table by using PIVOT or something. I'm trying to convert below table to the desired output like below.
Data Set:
question_id element_id
1 john
1 bran
1 o_siera
2 brook
2 joseph
2 o_daniel
2 o_cody
3 derick
3 james
3 sophia
3 o_sandra
3 o_ashley
Desired Result:
question_id element_id element
1 john o_siera
1 bran o_siera
2 brook o_daniel
2 joseph o_daniel
3 derick o_sandra
3 james o_sandra
3 sophia o_sandra
OR
OR can we achieve it in this way
question_id element_id element
1 john o_siera
1 bran
2 brook o_daniel,o_cody
2 joseph
3 derick o_sandra, o_ashley
3 james
3 sophia
Its not an ideal data model. Something like this should work except when a value that begins with 'o_%' is an element_id and not an element.
This was not tested.
select t1.question_id
,case when t1.element_id not like 'o_%' then t1.element_id else '' end element_id
,case when t2.element_id like 'o_%' then t2.element_id else '' end element
from table t1
join table t2 on t1.question_id=t2.question_id
I would suggest:
select t.*, max_o
from (select t.*,
max(case when element_id like 'o\_%' then element_id end) over (partition by question_id) as max_o
from t
) t
where element_id not like 'o\_%';
I have the following table:
WorkID WorkDesc
--------------------
1 ABCD
2 DEFG
3 HIJK
then I've the following table as the detail of table one:
WorkDetailID WorkID WorkDetailDesc
-----------------------------------------
1 1 001
2 1 002
3 2 006
4 2 007
5 3 015
Each WorkID is always have maximum 2 records and minimum is 1.
I want to have the following result:
WorkID WorkDesc WorkDetailID1 WorkDetailID2
-------------------------------------------------------
1 ABCD 1 2
2 DEFG 3 4
3 HIJK 5 null
Does anyone have an idea how to do that?
Thank you.
You can use pivot. I prefer conditional aggregation. In either case, you need a column for the pivoting. row_number() to the rescue:
select t1.workid, t1.workdesc,
max(case when t2.seqnum = 1 then t2.workdetailid end) as workdetailid1,
max(case when t2.seqnum = 2 then t2.workdetailid end) as workdetailid2
from t1 join
(select t2.*,
row_number() over (partition by t2.workid order by t2.workdetailid) as seqnum
from t2
) t2
on t1.workid = t2.workid
group by t1.workid, t1.workdesc
I have a table that look like this:
ID Name
-------
1 John
1 Mary
1 Jane
2 John
2 Mary
3 Jane
Knowing that every ID can only contain up to three names, I want to use a SELECT statement to turn this into the following:
ID Name1 Name2 Name3
--------------------
1 John Mary Jane
2 John Mary
3 Jane
Is there a way to do this in SQL?
If you know that there are at most three names, you can do this using conditional aggregation:
select id,
max(case when seqnum = 1 then name end) as name1,
max(case when seqnum = 2 then name end) as name2,
max(case when seqnum = 3 then name end) as name3
from (select t.*, row_number() over (partition by id order by name) as seqnum
from table t
) t
group by id;
With Oracle, you can use the PIVOT feature.
However, you'll need to RANK your rows first, over id-name pairs, and then you can do the pivot directive for (literally) the rank you just generated.
Pages to read:
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html
http://www.oracle-developer.net/display.php?id=506