How retrieve all parent and child rows population in Oracle sql? - sql

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

Related

How to get the list of people who do NOT have citizenship of country X in SQL

I have the 3 following tables
People
Id
Name
Age
1
Bob
23
2
John
25
3
Fred
37
4
Avery
42
Citizenship
Person_ID
Country_ID
1
2
1
1
2
1
2
5
3
2
3
6
4
3
4
4
Country
Country_ID
Country_Name
Capital_City
1
UK
London
2
France
Paris
3
Canada
Ottawa
4
Australia
Canberra
5
Germany
Berlin
6
Russia
Moscow
The goal here is to find all people who do NOT have French citizenship. My initial query was as follows
SELECT p.name
FROM People p
LEFT JOIN Citizenship ct
ON p.id = ct.person_id
LEFT JOIN Country c
ON ct.country_id = c.country_id
WHERE c.country_name != 'France';
However, the result doesn't seem to be correct. What condition am I missing in this query?

SQL Query - in how many countries we have users and in how many countries we don't have users

Need a SQL query that will answer this question.
Please tell us in how many countries we have users and in how many countries we don't have users. This should be presented in a table, in a single row and two columns (one with the number of countries in which we have users and one with the number of countries where we don't have users).
We have two tables: AllCountriesInTheWorld and AllUsers.
Table AllCountriesInTheWorld
country_id
country_name
1
USA
2
France
3
Italy
4
Portugal
5
Spain
6
Canada
7
UK
8
China
9
Japan
10
Germany
Table AllUsers
user_id
user_name
country_id
a1
John
4
b2
Jane
6
c3
Tony
6
d4
Dan
9
e5
Dave
1
Thanks a lot in advance guys!
If you LEFT JOIN the 2 tables on their common key,
then you can get all countries with or without users.
select *
from AllCountriesInTheWorld ctry
left join AllUsers usr
on usr.country_id = ctry.country_id
country_id
country_name
user_id
user_name
country_id
1
USA
e5
Dave
1
2
France
null
null
null
3
Italy
null
null
null
4
Portugal
a1
John
4
5
Spain
null
null
null
6
Canada
b2
Jane
6
6
Canada
c3
Tony
6
7
UK
null
null
null
8
China
null
null
null
9
Japan
d4
Dan
9
10
Germany
null
null
null
If you then GROUP BY the countries then you can COUNT how many USER_ID each country has.
count(usr.user_id) as total_users
country_id
total_users
1
1
2
0
3
0
4
1
5
0
6
2
7
0
8
0
9
1
10
0
Then just wrap that in a CTE or sub-query and use conditional aggregation on the total users.
;with CTE_COUNTRIES as (
...
)
select
sum(case when total_users > 0 then 1 else 0 end) as countries_with_users
, sum(case when total_users = 0 then 1 else 0 end) as countries_without_users
from CTE_COUNTRIES
countries_with_users
countries_without_users
4
6

Retrieve only the lowest Row from the duplicates [duplicate]

This question already has answers here:
How to select only the first rows for each unique value of a column?
(7 answers)
Closed 2 years ago.
Here I have the table which contains data like this:
Location No Days
----------------------
Callao 1 7
Callao 2 7
CHENNAI 3 6
SINGAPORE 4 30
SINGAPORE 5 7
SINGAPORE 6 7
LOS ANGELES 7 9
HONG KONG 7 11
HONG KONG 7 6
LOS ANGELES 8 6
HONG KONG 9 6
HONG KONG 9 4
LOS ANGELES 9 10
LOS ANGELES 9 9
LOS ANGELES 10 6
Here now I only want the row which has number with lowest days:
I want it like this,
Location No Days
---------------------
Callao 1 7
Callao 2 7
CHENNAI 3 6
SINGAPORE 4 30
SINGAPORE 5 7
SINGAPORE 6 7
HONG KONG 7 6
LOS ANGELES 8 6
HONG KONG 9 4
LOS ANGELES 10 6
I only want to remove duplication No. based on the highest value, I already tried many on my own but nothing is working.
Help me solve this, thanks in advance.
WITH
-- your input, thanks for pasting it in ..
indata(location,no,days) AS (
SELECT 'Callao',1,7
UNION ALL SELECT 'Callao',2,7
UNION ALL SELECT 'CHENNAI',3,6
UNION ALL SELECT 'SINGAPORE',4,30
UNION ALL SELECT 'SINGAPORE',5,7
UNION ALL SELECT 'SINGAPORE',6,7
UNION ALL SELECT 'LOS ANGELES',7,9
UNION ALL SELECT 'HONG KONG',7,11
UNION ALL SELECT 'HONG KONG',7,6
UNION ALL SELECT 'LOS ANGELES',8,6
UNION ALL SELECT 'HONG KONG',9,6
UNION ALL SELECT 'HONG KONG',9,4
UNION ALL SELECT 'LOS ANGELES',9,10
UNION ALL SELECT 'LOS ANGELES',9,9
UNION ALL SELECT 'LOS ANGELES',10,6
)
-- real query starts here, replace "," with "WITH" ..
,
w_filter AS (
SELECT
*
, ROW_NUMBER() OVER(PARTITION BY no ORDER BY days) AS fil
FROM indata
)
SELECT
location
, no
, days
FROM w_filter
WHERE fil=1
ORDER BY 2 ;
-- out location | no | days
-- out -------------+----+------
-- out Callao | 1 | 7
-- out Callao | 2 | 7
-- out CHENNAI | 3 | 6
-- out SINGAPORE | 4 | 30
-- out SINGAPORE | 5 | 7
-- out SINGAPORE | 6 | 7
-- out HONG KONG | 7 | 6
-- out LOS ANGELES | 8 | 6
-- out HONG KONG | 9 | 4
-- out LOS ANGELES | 10 | 6

In SQL Server how should i pivot for multiple columns

**branch** **category** **sales** **Stock** **Target**
Mumbai Panel 5 10 8
Mumbai AC 7 15 10
Mumbai Ref 8 3 12
Delhi Panel 10 15 11
Delhi AC 7 10 7
Delhi Ref 3 8 9
The above is my Query table i want the desired output to be in the form as given in the table below
**Branch** **qty** **Panel** **AC** **Ref**
Mumbai sale 5 7 8
Mumbai Stock 10 15 3
Mumbai Target 8 10 12
Delhi Sale 10 7 3
Delhi Stock 15 10 8
Delhi Target 11 7 9

eliminate duplicates SQL?

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);