Finding Percentage of Unmatching Records - sql

There are 2 tables, hometown (showing the hometown) and residence (showing the places that the residents live in the past 10 years). I want to find the percentage of the residents that lived or is living out of there hometown. A resident can live in multiple places, and the state_of_residence can be duplicated; as long as there is a record that shows he/she lives in a state other than his/her hometown, it should be counted.
resident_id
hometown_state
1
ny
2
ma
3
ct
4
pa
5
vt
resident_id
state_of_residence
1
ny
1
ct
1
ny
2
ma
3
ca
4
wa
4
tx
5
vt
The query should return 60% since resident 1, 3, and 4 have one or more state of residence other than his/her hometown. The query I'm having isn't return distinct state of residence, and putting DISTINCT inside a CASE statement return a syntax error. Much appreciated!
SELECT ROUND((SUM(CASE WHEN r.state_of_residence != h.hometown_state
THEN 1 ELSE 0 END)/COUNT(DISTINCT h.resident_id))*100,10)
FROM hometown h INNER JOIN residence r
ON h.resident_id=r.resident_id;

You can try to use COUNT condition aggregate function with DISTINCT instead of SUM aggregate function
SELECT COUNT(DISTINCT CASE WHEN r.state_of_residence <> h.hometown_state THEN h.hometown_state END) * 1.0
/ COUNT(DISTINCT h.resident_id) * 100
FROM hometown h
INNER JOIN residence r
ON h.resident_id=r.resident_id
GROUP BY r.resident_id

Related

SQL query to find the faculty which have taught every subject

I need to write a SQL query to find the faculty which has taught every subject (ie Sam)
With nested queries
Without using aggregate functions (no count, avg, min etc).
I can't seem to figure this out, would really appreciate some help =)
Faculty
fid
fname
fqualifications
fexperience
salary
deptname
100
Sam
ME CS
10
100000
IT
101
John
ME IT
8
80000
IT
102
Max
ME CS
9
90000
CS
103
Jenny
ME CS
5
50000
CS
Course
cid
cname
semester
1
SE
4
2
WT
4
3
CG
5
4
DBMS
5
Teaches
fid
cid
year
100
1
2019
100
2
2018
100
3
2020
100
4
2021
101
1
2017
101
2
2018
102
2
2018
102
3
2019
103
3
2020
103
4
2021
I used this query to find the output but according to the question I can't.
select * from faculty f
-> inner join teaches t
-> on f.fid=t.fid
-> inner join course c
-> on t.cid=c.cid
-> group by f.fid,f.fname
-> having count(*)=4;
OUTPUT:
fid
fname
fqualifications
fexperience
salary
deptname
fid
cid
year
cid
cname
semester
100
Sam
ME CS
10
100000
IT
100
1
2019
1
SE
4
Not the most efficient way to proceed, but with the requirements given to you, I would try and rephrase the query like this:
"A faculty that has taught every subject is a faculty that has not skipped even one subject".
Now, faculties that have skipped a subject will have a NULL when LEFT JOINed with the syllabus and all the subjects. Pseudo-SQL:
SELECT DISTINCT faculty.id FROM faculties
LEFT JOIN has_taught ON (has_taught.faculty_id = faculty.id)
LEFT JOIN subjects ON (has_taught.subject_id = subjects.id)
WHERE has_taught.faculty_id IS NULL;
or in some databases you maybe need
SELECT DISTINCT faculty.id FROM faculties
CROSS JOIN subjects
LEFT JOIN has_taught ON
(has_taught.faculty_id = faculty.id AND has_taught.subject_id = subjects.id)
WHERE has_taught.faculty_id IS NULL;
So, faculties that are NOT IN this list would naturally be
SELECT * FROM faculties
WHERE faculty.id NOT IN (
SELECT DISTINCT faculty.id ...
);
and this should only use nested queries, as requested.
Or with a further join
SELECT faculties.* FROM faculties
LEFT JOIN (
SELECT DISTINCT faculty.id ...
) AS they_skipped_some
ON (they_skipped_some.id = faculties.id)
WHERE they_skipped_some.id IS NULL

Count results that have different column value related to same ID

I'm new to SQL and looking for help on how to best do this.
I have 2 tables with the following columns:
Investors: Round ID, Investor Name, Investor City, Investor Country
Rounds: Round ID, Company Name, Company City, Company Country
I joined them to get this result
Round ID
Investor Country
Company Country
1
US
Spain
1
UK
Spain
1
Spain
Spain
2
France
Germany
2
UK
Germany
3
UK
Italy
3
Italy
Italy
I will need to get the number of investors (per round ID) which have their country different from the Company Country, So like for Round 1 I will have 2, for Round 2 it's 0 and for round 3 it's 1.
How could I do this?
Thank you for your help!
Just use conditional aggregation:
select round,
sum(case when investor_country <> company_company then 1 else 0 end) as cnt
from t
group by round;
Looking at your expected output, I think you need the count = 0 in case there do not exists a single record for investor country = company country and if there is, then you need all other record count.
You can use conditions as follows:
select round_id,
case when count(case when investor_country = company_company then 1 end) = 0
then 0
else count(case when investor_country <> company_company then 1 end)
end as cnt
from your_table t
group by round_id;
If you need diffrent counts:
SELECT
RoundId,
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS Count
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
If you need difrent count and when all result of a same Round are difrent you want zero:
SELECT
t.RoundId,
IIF(t.Count = t.DiffrentCount,0,t.DiffrentCount) 'Count'
FROM
(
SELECT
RoundId,
SUM(1) AS 'Count',
SUM(IIF(InvestorCountry != CompanyCountry,1,0)) AS 'DiffrentCount',
FROM
YOUR_TABLE_OR_VIEW
GROUP BY
RoundId
)t

How group by count from multiple tables

I have 3 different tables, country, city, and customer. Tables are shown below:
country table:
id country_name
1 UK
2 US
3 Brazil
:
n Canada
city table
id city_name postal_code country_id
1 London 30090 1
2 Dallas 20909 2
3 Rio 29090 3
4 Atlanta 30318 2
:
n Vancouver 32230 n
customer table
id customer_name city_id
1 John 1
2 Pete 3
3 Dave 2
4 May 2
5 Chuck 4
6 Sam 3
7 Henry 3
***country.id is references city.country_id, and city.id is references customer.city_id
I want to write a query that can extract the country name, city name and the count of the customer of the associate city. But with one condition, the query will return all cities with more customers than the average number of customers of all cities
It will look something like below, this is the correct output
UK London 2
Brazil Rio 3
but I kept getting this output, which isn't correct
UK London 2
US Dallas 2
US Atlanta 1
Brazil Rio 3
I fixed my SQL query but it doesn't give me the result that I want
SELECT country.country_name, city.city_name, COUNT(customer.city_id) from country
JOIN city on country.id = city.country_id
JOIN customer on city.id = customer.city_id
Group by city_name,country.country_name;
I am wondering how can I do this and fix my code?
add country.country_name in group by
SELECT country.country_name, city.city_name, COUNT(customer.city_id) from country
JOIN city on country.id = city.country_id
JOIN customer on city.id = customer.city_id
Group by city_name,country.country_name
You are missing country.country_name in the query it will give you error. As a general rule all columns on which aggregate function is not applied should be part of group by clause.
So either you write your query without country_name in the select or add country_name in the group by clause.

Hive sql: count and avg

I'm recently trying to learn Hive and i have a problem with a sql consult.
I have a json file with some information. I want to get the average for each register. Better in example:
country times
USA 1
USA 1
USA 1
ES 1
ES 1
ENG 1
FR 1
then with next consult:
select country, count(*) from data;
I obtain:
country times
USA 3
ES 2
ENG 1
FR 1
then i should get next out:
country avg
USA 0,42 (3/7)
ES 0,28 (2/7)
ENG 0,14 (1/7)
FR 0,14 (1/7)
I don't know how i can obtain this out from the first table.
I tried:
select t1.country, avg(t1.tm),
from (
select country,count(*)as tm from data where not country is null group by country
) t1
group by t1.country;
but my out is wrong.
Thanks for help!! BR.
Divide the each group count by total count to get the result. Use Sub-Query to find the total number of records in your table
Try this
select t1.country, count(*)/IFNULL((select cast(count(*) as float) from data),0)
from data
group by t1.country;

Specific Ordering in SQL

I have a SQL Server 2008 database. In this database, I have a result set that looks like the following:
ID Name Department LastOrderDate
-- ---- ---------- -------------
1 Golf Balls Sports 01/01/2015
2 Compact Disc Electronics 02/01/2015
3 Tires Automotive 01/15/2015
4 T-Shirt Clothing 01/10/2015
5 DVD Electronics 01/07/2015
6 Tennis Balls Sports 01/09/2015
7 Sweatshirt Clothing 01/04/2015
...
For some reason, my users want to get the results ordered by department, then last order date. However, not by department name. Instead, the departments will be in a specific order. For example, they want to see the results ordered by Electronics, Automotive, Sports, then Clothing. To throw another kink in works, I cannot update the table schema.
Is there a way to do this with a SQL Query? If so, how? Currently, I'm stuck at
SELECT *
FROM
vOrders o
ORDER BY
o.LastOrderDate
Thank you!
You can use case expression ;
order by case when department = 'Electronics' then 1
when department = 'Automotive' then 2
when department = 'Sports' then 3
when department = 'Clothing' then 4
else 5 end
create a table for the departments that has the name (or better id) of the department and the display order. then join to that table and order by the display order column.
alternatively you can do a order by case:
ORDER BY CASE WHEN Department = 'Electronics' THEN 1
WHEN Department = 'Automotive' THEN 2
...
END
(that is not recommended for larger tables)
Here solution with CTE
with c (iOrder, dept)
as (
Select 1, 'Electronics'
Union
Select 2, 'Automotive'
Union
Select 3, 'Sports'
Union
Select 4, 'Clothing'
)
Select * from c
SELECT o.*
FROM
vOrders o join c
on c.dept = o.Department
ORDER BY
c.iOrder