While transposing single columns is pretty straight forward I need to transpose a large amount of data with 3 sets of , 10+ related columns needed to be transposed.
create table test
(month int,year int,po1 int,po2 int,ro1 int,ro2 int,mo1 int,mo2 int, mo3 int);
insert into test
values
(5,2013,100,20,10,1,3,4,5),(4,2014,200,30,20,2,4,5,6),(6,2015,200,80,30,3,5,6,7) ;
select * FROM test;
gives
month
year
po1
po2
ro1
ro2
mo1
mo2
mo3
5
2013
100
20
10
1
3
4
5
4
2014
200
30
20
2
4
5
6
6
2015
200
80
30
3
5
6
7
Transposing using UNPIVOT
select
month, year,
PO, RO, MO
from ( SELECT * from test) src
unpivot
( PO for Description in (po1, po2))unpiv1
unpivot
(RO for Description1 in (ro1, ro2)) unpiv2
unpivot
(MO for Description2 in (mo1, mo2, mo3)) unpiv3
order by year
Gives me this
month
year
PO
RO
MO
5
2013
100
10
3
5
2013
100
10
4
5
2013
100
10
5
5
2013
100
1
3
5
2013
100
1
4
5
2013
100
1
5
5
2013
20
10
3
5
2013
20
10
4
5
2013
20
10
5
5
2013
20
1
3
5
2013
20
1
4
5
2013
20
1
5
4
2014
200
20
4
4
2014
200
20
5
4
2014
200
20
6
4
2014
200
2
4
4
2014
200
2
5
4
2014
200
2
6
4
2014
30
20
4
4
2014
30
20
5
4
2014
30
20
6
4
2014
30
2
4
4
2014
30
2
5
4
2014
30
2
6
6
2015
200
30
5
6
2015
200
30
6
6
2015
200
30
7
6
2015
200
3
5
6
2015
200
3
6
6
2015
200
3
7
6
2015
80
30
5
6
2015
80
30
6
6
2015
80
30
7
6
2015
80
3
5
6
2015
80
3
6
6
2015
80
3
7
I will like to turn it to something like this. Is that possible?
month
year
PO
RO
MO
5
2013
100
10
3
5
2013
20
1
4
5
2013
0
0
5
4
2014
200
20
4
4
2014
30
2
5
4
2014
0
0
6
6
2015
200
30
5
6
2015
80
3
6
6
2015
0
0
7
Maybe use a query like below which creates rows as per your design using CROSS APPLY
select month,year,po,ro,mo from
test cross apply
(values (po1,ro1,mo1), (po2,ro2,mo2),(0,0,mo3))v(po,ro,mo)
see demo here
Unpivot acts similar as union,Use union all in your case
SELECT month,
year,
po1 AS PO,
ro1 AS RO,
mo1 AS MO
FROM test
UNION ALL
SELECT month,
year,
po2,
ro2,
mo2
FROM test
UNION ALL
SELECT month,
year,
0,
0,
mo2
FROM test
I have a table "TB_Population" with some records about the population from all over the world.
at this time I want to calculate each title's population in particular row
and demonstrate each level in that table.
I have this table with the following data:
ID TITLE PARENT_ID POPULATION
1 WORLD 10
2 AFRICA 1 5
3 ASIA 1 10
4 EUROPE 1 4
5 GERMANY 4 6
6 FRANCE 4 10
7 ITALY 4 4
8 JAPAN 3 6
9 MORROCO 2 1
10 SPAIN 4 9
11 INDIA 3 8
12 PORTUGAL 4 2
13 USA 14 10
14 AMERICA 1 10
15 NEWYORK 13 5
The expected output table should be as below
ID TITLE POPULATION LEVEL
1 WORLD 100 1
2 AFRICA 6 2
3 ASIA 24 2
4 EUROPE 35 2
5 GERMANY 6 3
6 FRANCE 10 3
7 ITALY 4 3
8 JAPAN 6 3
9 MORROCO 1 3
10 SPAIN 9 3
11 INDIA 8 3
12 PORTUGAL 2 3
13 USA 15 3
14 AMERICA 25 2
15 NEWYORK 5 4
Thanks and best regards
The tricky part which I see here is you want the LEVEL of title from "BOTTOM TO TOP" and POPULATION from "TOP TO BOTTOM". For example, AMERICA's level has to be 2 which means the LEVEL has to be measured from AMERICA -> WORLD, but AMERICA's population has to be 25 which is the sum of population measured from AMERICA -> NEWYORK. So, I tried this:
SELECT TOP_TO_BOTTOM.TITLE_ALIAS, TOP_TO_BOTTOM.TOTAL_POPULATION, BOTTOM_TO_TOP.MAX_LEVEL FROM
(SELECT TITLE_ALIAS, SUM(POPULATION) AS "TOTAL_POPULATION" FROM
(SELECT CONNECT_BY_ROOT TITLE AS "TITLE_ALIAS", POPULATION
FROM TB_POPULATION
CONNECT BY PRIOR ID = PARENT_ID)
GROUP BY TITLE_ALIAS) "TOP_TO_BOTTOM"
INNER JOIN
(SELECT TITLE_ALIAS, MAX(LEV) AS "MAX_LEVEL" FROM
(SELECT CONNECT_BY_ROOT TITLE AS "TITLE_ALIAS", LEVEL AS "LEV"
FROM TB_POPULATION
CONNECT BY PRIOR PARENT_ID = ID)
GROUP BY TITLE_ALIAS) "BOTTOM_TO_TOP"
ON
BOTTOM_TO_TOP.TITLE_ALIAS = TOP_TO_BOTTOM.TITLE_ALIAS
ORDER BY BOTTOM_TO_TOP.MAX_LEVEL;
You can have a look at the simulation here: https://rextester.com/HFTIH47397.
Hope this helps you
If i have a Data Frame(df) as :
Year Rate
2001 10
2001 3
2001 5
2001 3
2001 6
2002 2
2002 7
2002 4
2002 9
2002 8
... ...
2018 8
2018 6
2018 4
2018 6
2018 5
How do i get a Data Frame that show only first 2 rows of each years, like:
Year Rate
2001 10
2001 3
2002 2
2002 7
... ...
2018 8
2018 6
Thanks
Use GroupBy.head:
df1 = df.groupby('Year').head(2)
print (df1)
Year Rate
0 2001 10
1 2001 3
5 2002 2
6 2002 7
10 2018 8
11 2018 6
Thanks in advance for any assistance you can provide. I have spent hours on this with no luck.
I'm working with an indented bill of material table which has an end part id, a sequence number, a level and a quantity. The goal is to determine the total cumulative quantity of each row on this table.
What makes this difficult is that to determine the total quantity, the child quantity needs to be multiplied by it's parent quantity. The parent quantity of that parent needs to be multiplied by it's parent quantity and so on.
For example, a level 3 part has a component quantity of 5. It's parent the level 2 part has a component quantity of 2. It's parent the level 1 part has a component quantity of 3. This means the level 3 part total quantity is 30 (3 X 2 X 5).
With the assistance of SO (specifically #KKK) the parent quantity was able to be calculated in the below query. After this was resolved I realized I now need two additional columns, one that shows the Rolled/Cumulative quantities of the parent rows and one that shows the total quantity of the child.
The attached screenshot has the two columns that need to be added highlighted in yellow. Here is the current SQL (using Oracle 10.2) for the columns that are not in yellow:
select
end_part_id, sort_seq_no, indented_lvl, comp_qty,
(select distinct first_value(a.comp_qty) over (order by a.sort_seq_no desc, TRIM(a.indented_lvl) desc)
from
report_table a
where
a.end_part_id = b.end_part_id
and a.sort_seq_no < b.sort_seq_no
and TRIM(a.indented_lvl) < TRIM(b.indented_lvl)) as "PARENT_QTY"
from report_table b
Expected Results
END_PART_ID SORT_SEQ_NO INDENTED_LVL COMP_QTY PARENT_QTY ROLLED_PARENT QTY TOTAL_QTY
PARTX 1 1 2 1 1 2
PARTX 2 2 5 2 2 10
PARTX 3 3 2 5 10 20
PARTX 4 4 1 2 20 20
PARTX 5 5 1 1 20 20
PARTX 6 6 1 1 20 20
PARTX 7 5 4 1 20 80
PARTX 8 6 1 4 80 80
PARTX 9 2 7 2 2 14
PARTX 10 3 2 7 14 28
PARTX 11 3 2 7 14 28
PARTX 12 4 1 2 28 28
PARTX 13 4 1 2 28 28
PARTX 14 3 8 7 14 112
PARTX 15 1 1 1 1 1
PARTX 16 2 7 1 1 7
PARTX 17 3 2 7 7 14
PARTX 18 3 2 7 7 14
PARTX 19 4 1 2 14 14
PARTX 20 4 1 2 14 14
How do I eliminate the duplicates?
It must be 10 rows, show every student ID (1x).
Ive tried this 2 diff ways. (see below)
( the common field is class_id)
SQL> select distinct(student_id),event.class_id, event.event_id, event.event_name
2 from student_class
3 inner join event on event.class_id = student_class.class_id
4 where student_class.class_id = '10'
5 order by student_id desc;
STUDENT_ID CLASS_ID EVENT_ID EVENT_NAME
---------- ---------- ---------- --------------------------------------------------
20 10 5 PICKUP SOCCER GAME
20 10 2 Flag FOOtball Game
18 10 2 Flag FOOtball Game
18 10 5 PICKUP SOCCER GAME
16 10 2 Flag FOOtball Game
16 10 5 PICKUP SOCCER GAME
12 10 5 PICKUP SOCCER GAME
12 10 2 Flag FOOtball Game
9 10 5 PICKUP SOCCER GAME
9 10 2 Flag FOOtball Game
8 10 2 Flag FOOtball Game
8 10 5 PICKUP SOCCER GAME
6 10 2 Flag FOOtball Game
6 10 5 PICKUP SOCCER GAME
4 10 5 PICKUP SOCCER GAME
4 10 2 Flag FOOtball Game
3 10 2 Flag FOOtball Game
3 10 5 PICKUP SOCCER GAME
2 10 5 PICKUP SOCCER GAME
2 10 2 Flag FOOtball Game
SQL> select distinct(student_id), student_class.class_id,
event.event_id, event.event_date_time
from student_class
inner join event on event.class_id = student_class.class_id
order by student_id desc;
STUDENT_ID CLASS_ID EVENT_ID EVENT_DAT
---------- ---------- ---------- ---------
22 9 1 09-NOV-99
21 2 6 20-NOV-99
21 9 1 09-NOV-99
20 9 1 09-NOV-99
20 10 2 19-JAN-99
20 10 5 09-JUL-99
18 9 1 09-NOV-99
18 10 2 19-JAN-99
18 10 5 09-JUL-99
17 9 1 09-NOV-99
16 2 6 20-NOV-99
16 9 1 09-NOV-99
16 10 2 19-JAN-99
16 10 5 09-JUL-99
15 9 1 09-NOV-99
14 9 1 09-NOV-99
13 9 1 09-NOV-99
12 2 6 20-NOV-99
12 9 1 09-NOV-99
12 10 2 19-JAN-99
12 10 5 09-JUL-99
11 2 6 20-NOV-99
11 9 1 09-NOV-99
9 10 2 19-JAN-99
9 10 5 09-JUL-99
8 2 6 20-NOV-99
8 10 2 19-JAN-99
8 10 5 09-JUL-99
7 2 6 20-NOV-99
6 10 2 19-JAN-99
6 10 5 09-JUL-99
4 10 2 19-JAN-99
4 10 5 09-JUL-99
3 10 2 19-JAN-99
3 10 5 09-JUL-99
2 2 6 20-NOV-99
2 9 1 09-NOV-99
2 10 2 19-JAN-99
2 10 5 09-JUL-99
you can do this by following methods
create table table_name2 as select distinct * from table_name1;
drop table table_name1;
rename table_name2 to table_name1;
or by this query
DELETE FROM table_name A WHERE ROWID > (SELECT min(rowid) FROM table_name B WHERE A.key_values = B.key_values);