How to write query in the following case? - sql

I have the following table. How do I query
Table Team is as follows:
ID,Name,City,League
1,Name1,City1, A
2,Name2,City1, B

The trick is to get a COUNT(DISTINCT League) per city, and compare that number to the total number of leagues COUNT(DISTINCT League) across the whole table.
SELECT
City,
COUNT(DISTINCT League) AS numleagues
FROM yourtable
GROUP BY City
/* Only cities which have the same number of distinct leagues as the total number of distinct leagues */
HAVING COUNT(DISTINCT League) = (SELECT COUNT(DISTINCT League) FROM yourtable)
Here it is in action in SQLFiddle

All cities for which there does not exist a League which is not in the list of Leagues associated with the city:
SELECT DISTINCT City FROM Teams T1 WHERE NOT EXISTS
(SELECT * FROM Teams T2 WHERE League NOT IN
(SELECT League FROM Teams T3 WHERE T3.City = T1.City))

Almost exactly as you worded it in English, but with a twist... You want all cities that have a Name in all leagues, or to rephrase, you want all Cities where there does not exist a League that does not have a name in it from that city.;..
Select Distinct City From Table t
Where Not Exists
(Select Distinct League From Table L
Where Not Exists
(Select * From Table
Where City = t.City
And League = L.League
And Name Not in
(Select distinct Name from table
Where City = t.City) ))

Related

Sql query for the lowest score per country

I have a database with 3 tables. In table country I have id and name columns. The sport table also has id and name columns. Finally, the table match has id, player1, and player2(that are ids of country that play one against other), winner_id (id of country that won the match) and sport_id of the sport which was played. The least wins means that I just need in which sport country had the least wins, no matther on played matches.
I want to show the sport per country with the least wins. It should look like this:
Country
Sport
Wins
France
Basketball
2
How can I construct this query? I'm using SQL Server.
Data in table look like this. Table countries:
country_id
name
1
France
2
England
Table sport:
sport_id
name
1
Footbal
2
Basketball
Table match:
match_id
player1
player2
winner_id
sport_id
1
3
1
3
1
2
6
4
4
2
I want to note that the used wording with least wins is not clear, in my solution with least wins means most matches played with least wins.
To get this ranking, we need to know how many matches a country has played in each sport and how many of those have been won.
SELECT
country.name AS country,
sport.name AS sport,
sport_wins.wins
FROM
country
OUTER APPLY (
SELECT TOP 1
t.match_count,
COALESCE(t.wins, 0) AS wins,
t.sport_id
FROM (
SELECT
COUNT(*) AS match_count,
m_c.sport_id,
t.wins
FROM match m_c
OUTER APPLY (
SELECT
COUNT(*) AS wins,
match.sport_id
FROM match
WHERE country.country_id = match.winner_id
AND match.sport_id = m_c.sport_id
GROUP BY match.sport_id
) t
WHERE country.country_id IN (m_c.player1, m_c.player2)
GROUP BY m_c.sport_id, t.wins
) t
ORDER BY t.wins ASC, t.match_count DESC
) sport_wins
JOIN sport ON sport.sport_id = sport_wins.sport_id
Please, check a demo.
If you do not take into account losses, but only the number of wins is of interest, you can use a query like this one
WITH cte AS (
SELECT
country.country_id,
sport.sport_id,
SUM(CASE WHEN match.winner_id = country.country_id THEN 1 ELSE 0 END) AS wins
FROM country
CROSS JOIN sport
JOIN match ON match.sport_id = sport.sport_id
AND country.country_id IN (match.player1, match.player2)
GROUP BY country.country_id, sport.sport_id
)
SELECT
country.name,
sport.name,
t.min_wins AS wins
FROM (
SELECT
country_id,
MIN(wins) AS min_wins
FROM cte
GROUP BY country_id
) t
JOIN cte ON cte.country_id = t.country_id AND cte.wins = min_wins
JOIN country ON cte.country_id = country.country_id
JOIN sport ON cte.sport_id = sport.sport_id
This query takes into account the fact that the country participates in matches in sport, so if a country does not compete in a sport, that sport will not be included in the statistics as it will have 0 wins and this will be the minimum value.
Please, check a demo
You need to first cross-join the sports with the countries, then get the total.
Then you can use a row-number approach to get the bottom country in each sport
SELECT
c.Country,
c.Sport,
c.Wins
FROM (
SELECT
c.name Country,
s.name Sport,
COUNT(m.winner_id) Wins,
ROW_NUMBER() OVER (PARTITION BY s.sport_id, s.name ORDER BY COUNT(m.winner_id)) rn
FROM country c
CROSS JOIN sport s
LEFT JOIN [match] m
ON s.sport_id = m.sport_id AND m.winner_id = c.country_id
GROUP BY
s.sport_id,
s.name,
c.country_id,
c.name
) c
WHERE c.rn = 1;

SQL derived table. Easy SQL

Hi i get the error 'Every derived table must have its own alias' what can i do about it??
My question is :
Show team ID and names from teams from Germany who have never played in UEFA Champions league
UEFA Champions league = 1
Cid= Competions ID
Tid = Team ID
SELECT teams.TID, teams.name from(
SELECT Tid1 FROM(
(SELECT tid1,cid FROM matches
WHERE tid1 IN (SELECT tid FROM teams WHERE country='Germany')
UNION
SELECT tid2,cid FROM matches
WHERE tid2 IN (SELECT tid FROM teams WHERE country='Germany'))
)WHERE cid <> (SELECT cid FROM competitions WHERE cid='1'))
INNER JOIN matches ON tid1=team.tid;
I have tried looking at others derived soulutions but i cant get to work with mine...
It looks like its asking for you to give alias to the tables you have created within the query. Try this.
EFA Champions league = 1
Cid= Competions ID
Tid = Team ID
SELECT teams.TID, teams.name from(
SELECT Tid1 FROM(
(SELECT tid1,cid FROM matches
WHERE tid1 IN (SELECT tid FROM teams WHERE country='Germany')
UNION
SELECT tid2,cid FROM matches
WHERE tid2 IN (SELECT tid FROM teams WHERE country='Germany'))ALIAS1
)WHERE cid <> (SELECT cid FROM competitions WHERE cid='1')) ALIAS2
INNER JOIN matches ON tid1=team.tid;

List top 20 schools based on number of applicantions for specific schools

I have two tables table school list school ID and school name, and there is another table which contains number of applicants and their state. I need to write a SQL query to list top 20 schools based on number of applicants for specific state (NY, CA)
tbl1 columns (SchoolID, Schoolname)
tbl2 columns (applicantID, schoolID, applicantName, state)
Thanks,
Try something like (assuming tbl2 contains Foreign Key -> SchoolID)
SELECT TOP 20
tbl1.SchoolID
,tbl1.Schoolname
,Count(tbl2.applicationID) NumberOfApplicants
FROM Table1 tbl1 INNER JOIN Table2 tbl2 ON tbl2.SchoolID = tbl1.SchoolID
WHERE tbl2.state = 'CA'
GROUP BY tbl2.state
ORDER BY NumberOfApplicants DESC
SQLFIDDLE DEMO

sql query to select matching rows for all or nothing criteria

I have a table of cars where each car belongs to a company. In another table I have a list of company locations by city.
I want to select all cars from the cars table whose company has locations on all cities passed into the stored procedure, otherwise exclude those cars all together even if it falls short of one city.
So, I've tried something like:
select id, cartype from cars where companyid in
(
select id from locations where cityid in
(
select id from cities
)
)
This doesn't work as it obviously satisfies the condition if ANY of the cities are in the list, not all of them.
It sounds like a group by count, but can't make it work with what I tried.
I"m using MS SQL 2005
One example:
select id, cartype from cars c
where ( select count(1) from cities where id in (...))
= ( select count(distinct cityid)
from locations
where c.companyid = locations.id and cityid in (...) )
Maybe try counting all the cities, and then select the car if the company has the same number of distinct location cities are there are total cities.
SELECT id, cartype FROM cars
WHERE
--Subquery to find the number of locations belonging to car's company
(SELECT count(distinct cities.id) FROM cities
INNER JOIN locations on locations.cityid = cities.id
WHERE locations.companyId = cars.companyId)
=
--Subquery to find the total number of locations
(SELECT count(distinct cities.id) FROM cities)
I haven't tested this, and it may not be the most efficient query, but I think this might work.
Try this
SELECT e.*
FROM cars e
WHERE NOT EXISTS (
SELECT 1
FROM Cities p
WHERE p.location = e.Location
)

SQL Multiple Duplicate Row Detection

I'm trying to determine a correct way to isolate rows within a table that have the same values in 2 columns.
There are two tables, one (Name) with the person's names and IDs, and the other one (Nation) with people's IDs and their nations. I join the two tables with inner join, and now the new table columns consist of an ID, first name, last name, and nation. If I want to find pairs of people who have the same last name and are from the same nation, why isn't
select ID, FName, LName, Nation
from (Name inner join Nation on Name.ID = Nation.ID)
group by Name, Nation
having count(Name) > 1 and count(Nation) > 1
working?
I'm aiming for the result to be a table with columns:
ID -------First--------------- Last ---------Nation
where the last names and nations will be identical pairs while first names will be different.
I feel like the group by part isnt appropriate, but is there even an alternate way? Thanks for any help.
If you are using MS SQL Server:
select
*
from
(
select
Name.*,
Nation.Nation,
cnt = count(*) over(partition by LName, Nation)
from Name
join Nation on Nation.ID = Name.ID
) t
where cnt > 1
Try this:
SELECT * FROM (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) a
INNER JOIN (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) b ON (a.LName = b.LName AND a.Nation = b.Nation)
WHERE a.ID < b.ID
As Simon Righarts hinted, something's not right with the design.
Scenario 1)
If a name can have multiple nations, you would have 3 tables implementing an n:m relationship.
CREATE TABLE name (name_id int, name text, ...);
CREATE TABLE nation (nation_id int, nation text, ...);
CREATE TABLE nationality (name_id int references name(name_id)
,nation_id int references nation(nation_id)
... );
Query for the scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nationality na USING (name_id)
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, na.nation_id
FROM name a
JOIN nationality na USING (name_id)
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id)
Scenario 2)
If a name can only have one nation, there would be a column nation_id in the table name:
CREATE TABLE name (name_id int
,name text
,nation_id int references nation(nation_id), ...);
CREATE TABLE nation (nation_id int, nation text, ...);
Query for this scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, a.nation_id
FROM name a
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id);
All multiple occurrences are included here, not just "pairs" - assuming you meant that.
Your actual description doesn't fit either scenario.