Nested 'Where'? - sql

I have a table named Actor, with only a column for City (CityId). I want to return the number of actors in a particular State (StateId). The catch however is that I have separate tables for City, County, and finally State (City has CountyId, County has StateId). How do I this in a T-SQL query?
I have a solution that involves nested Select statements, something like:
SELECT COUNT(1)
FROM Actor a
WHERE a.CityId IN
(SELECT CityId FROM City WHERE CountyId IN...)
...but is there a more efficient way to do this? Thanks

You can use this query to get your output
----------------------------------------------------------
SELECT COUNT(ActorId)
FROM Actor a
INNER JOIN City c ON a.cityId = c.cityId
INNER JOIN Country con ON c.countryId = con.countryId
INNER JOIN STATE s ON con.stateId = s.stateId
GROUP BY s.stateId

Use JOINS to query your data.
I am using INNER JOIN here.
Assuming that you have CountryId in your City Table, You can do it following way.
In case you don't have countryId in your City Table you have to apply one more INNER JOIN on State Table.
SELECT COUNT(1) FROM Actor a INNER JOIN
City b ON a.CityId = b.CityId
WHERE b.CountryId IN (...)

You can easily put the JOINS across different table that you have and then use the Group By clause to find out the total number of actors from specific state.
I have used the column name on the basis of my wild guess, you can change them with the original name that you have in your database.
SELECT StateId,
Count(ActorId) AS Total
FROM ACTOR
INNER JOIN City ON Actor.CityId = City.CityId
INNER JOIN County ON County.CountyId = City.CountyId
INNER JOIN State ON State.StateId = County.StateId
GROUP BY State.StateId

Assuming the relation names, you can do something like this with joins:
select s.ID, s.Name, count(*)
from Actors a
inner join Cities c on c.ID = a.CityID
inner join County cn on cn.ID = c.CountyID
inner join State s on s.ID = cn.StateID
group by s.ID, s.Name
If you only need the StateId you don't even need to join with states, this will do:
select cn.StateID, count(*)
from Actors a
inner join Cities c on c.ID = a.CityID
inner join County cn on cn.ID = c.CountyID
group by cn.StateID

Related

How to combine Inner Join and Left Join in SQL Query statement?

Given this Diagram:
What is the right way to use join that will includes all necessary fields from different tables (person name, employee number, status of contracts, job name, department name, pcn/item name, country, and religion)? BUT I want also to include all persons that choose not to put either thier country or religion. I have this query:
SELECT persons.fullname, religions.religion_name, countries.country_name
FROM countries INNER JOIN (religions INNER JOIN (persons INNER JOIN
((jobs INNER JOIN (departments INNER JOIN pcns ON departments.ID = pcns.department_id) ON jobs.ID = pcns.job_id)
INNER JOIN (employees INNER JOIN contracts ON employees.ID = contracts.employee_id) ON pcns.ID = contracts.pcn_id)
ON persons.ID = employees.person_id) ON religions.ID = persons.religion) ON countries.ID = persons.country_id;
I used LEFT JOIN but I got an error. Right now, I only query all my tables except for countries and religions then I made a function that whenever a user clicks particular person this function will return its religion and/or country. I am just curious how to achieve it in a SELECT query.

Why Oracle OFFSET and LIMIT is not working when using DISTINCT

I need to get clarified the below situation.
I have a city, country table and I need to validate this will some other tables and get the city country results ordered by the country. Here's my query for that
SELECT distinct
c.code as CITY ,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country
And this provides the results as
Now when I use OFFSET and LIMIT values in the below query
SELECT distinct
c.code as CITY,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY.
I expect to get ADOR, ADPC, ADSJ, ADVD, ALV as the output.
Why is that and what I am missing here in this query.
When I do the following I get the expected outcome
SELECT CITY, COUNTRY FROM ( SELECT distinct
c.code as CITY,
c.country as COUNTRY from location_info li
inner join someTable s on li.loc_id = s.some_id
inner join city c on s.city = c.code
ORDER BY c.country ) OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY.
The issue is that the ORDER BY is not stable. What that means is that you have ties in the key values. So, running the query two times might result in different orderings.
This is easily fixed by including more keys in the order by so the order by keys uniquely identify each row:
select distinct c.code as CITY, c.country as COUNTRY
from location_info li join
someTable s
on li.loc_id = s.some_id join
city c
on s.city = c.code
order by c.country, c.code;

sqlite: count and group by clause gives not the result expected

on sqlite, I have the tables
papers: rero_id, doi, year
writtenby: rero_id, authorid, instid
authors: author_id, name, firstname
inst: inst_id, name, see_id
inst is a table of Institutions: Universities and so on.
Each line in writtenby gives a paper, an author, an institution this author was attached at that time. There can be more then one institution and the couple paper, authorid is repeated for each institution.
For a given author, I want a list and a count of the institutions he has cohautored paper with.
For a list I tried
SELECT inst.name as loc
FROM (
(authors INNER JOIN writtenby ON authors.authorid =
writtenby.authorid)
INNER JOIN writtenby AS writtenby_1 ON writtenby.rero_id =
writtenby_1.rero_id
)
INNER JOIN authors AS auth_1 ON writtenby_1.authorid =
auth_1.authorid
inner join inst on writtenby_1.instid = inst.inst_id
WHERE (authors.name) ="Doe" AND (authors.firstname)= "Joe"
ORDER BY loc
I got a list that seems ok.
Now, I would like to regroup these institution names and have a count.
I tried
SELECT inst.name, count(inst.name)
FROM (
(authors INNER JOIN writtenby ON authors.authorid =
writtenby.authorid)
INNER JOIN writtenby AS writtenby_1 ON writtenby.rero_id =
writtenby_1.rero_id
)
INNER JOIN authors AS auth_1 ON writtenby_1.authorid =
auth_1.authorid
inner join inst on writtenby_1.instid = inst.inst_id
GROUP BY inst.name
HAVING (authors.name) ="Doe" AND (authors.firstname)= "John"
I have only three line and not a count of the institutions listed from the first query.
Thanks for correcting me !
François
Try using where instead of having
SELECT inst.name, count(inst.name)
FROM (
(authors INNER JOIN writtenby ON authors.authorid =
writtenby.authorid)
INNER JOIN writtenby AS writtenby_1 ON writtenby.rero_id =
writtenby_1.rero_id
)
INNER JOIN authors AS auth_1 ON writtenby_1.authorid =
auth_1.authorid
inner join inst on writtenby_1.instid = inst.inst_id
where authors.name ='Doe' AND authors.firstname= 'John'
GROUP BY inst.name
I got this that works,
SELECT inst.name as loc, count(*) as c
FROM (
(authors INNER JOIN writtenby ON authors.authorid = writtenby.authorid)
INNER JOIN writtenby AS writtenby_1 ON writtenby.rero_id =
writtenby_1.rero_id
inner join inst on writtenby_1.instid = inst.inst_id
)
INNER JOIN authors AS auth_1 ON writtenby_1.authorid = auth_1.authorid
WHERE (authors.name) ="Doe" AND (authors.firstname)= "John"
GROUP BY inst.name
ORDER BY c DESC
I still can use a where clause, and that's not the same as having...
And thanks to fa6 who gave the answer below
F.

creating possible combinations list from Many to Many relation

I have a Set of tables
Hotels
Countries
Regions
Cities
Hotel_Types
and a many to many relations table named Mappings which contains all the relations/mappings which contains info like
id, hotel_id, reference_type, reference_id, ...
where reference_type can be a Country, Region, City, Hotel_Type etc
and reference_id is the id of said entity like country_id or city_id etc.
I need to create a list of all possible combinations of
Country_Name+Hotel_Type_Name
Region_Name+Hotel_Type_Name
City_Name+Hotel_Type_Name
Where the hotels exist. Any help how may I access the names from different tables and how to combine them
I am implying few things here but you could do inner joins in this way:
select name, hotel_type_name
from (select c.country_name as name, h.hotel_type_name Mappings m inner join Countries c on m.reference_type='Country' and m.reference_id=c.country_id inner join hotel_Types h on m.reference_type='Hotel_type' and m.reference_id=h.hotel_type_id) union all
(select c.region_name as name, h.hotel_type_name Mappings m inner join Regions r on m.reference_type='Region' and m.reference_id=r.region_id inner join Hotel_Types h on m.reference_type='Hotel_type' and m.reference_id=h.hotel_type_id) union all
(select c.city_name as name, h.hotel_type_name Mappings m inner join Cities ci on m.reference_type='City' and m.reference_id=ci.city_id inner join Hotel_Types h on m.reference_type='Hotel_type' and m.reference_id=h.hotel_type_id)
This will list unique combinations of Country_Name+Hotel_Type_Name
--link hotels to hotel_type
with Hotel_Hotel_Types as (
select h.hotel_id
,ht.reference_id as hotel_types_id
from Hotels as h
inner join Mappings ht on ht.reference_type = 'Hotel_Type' and h.hotel_id = ht.hotel_id
)
--link hotels to Country_Name
,Hotel_Country_Name as (
select h.hotel_id
,c.reference_id as countries_id
from Hotels as h
inner join Mappings c on c.reference_type = 'Country' and h.hotel_id = c.hotel_id
)
select distinct ht.*, c.*
from Hotel_Hotel_Types hht
inner join Hotel_Types ht on ht.hotel_types_id = hht.hotel_types_id
inner join Hotel_Country_Name hc on hc.hotel_id = hht.hotel_id
inner join Countries c on с.countries_id = hc.countries_id
Region_Name+Hotel_Type_Name and City_Name+Hotel_Type_Name can be queried using similar sqls.

Retrive counts of two columns from two diffrent tables with third table using join query in SQL

I have 3 tables: COUNTRY, STATE, CITY
This is my Country table with two columns:
CountryID, Name
This is my State table:
This is my City table:
I want to retrieve the count of states and cities according to the country table using join query.
Skipping the fact that your question is not asked well - try this query, it should work for you:
WITH
tab_a AS (
SELECT c.countryid, COUNT (s.stateid) AS state_num
FROM country c
LEFT JOIN state s ON c.countryid = s.countryid
GROUP BY c.countryid
),
tab_b AS (
SELECT c.countryid, COUNT (cc.cityid) city_num
FROM country c
LEFT JOIN state s ON c.countryid = s.countryid
LEFT JOIN city cc ON s.stateid = cc.stateid
GROUP BY c.countryid
)
SELECT a.countryid,
a.state_num,
b.city_num
FROM tab_a a JOIN tab_b b ON a.countryid=b.countryid