SQL derived table. Easy SQL - 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;

Related

unable to count the occurrence of a guest in 2 different restaurants and display guest name

The question im trying to answer is : to find the names of guest who visited more than 2 different restaurants on 15-JUNE-20.
There is a:
Guest table with GID,Gname
Visit table with VID, GID, RESTID, VDATE
Restaurant table with RESTID, RNAME
whenever i tried introducing the groupby i would get the error
SELECT GuestN.GID, GuestN.Gname
FROM GuestN
WHERE GuestN.GID IN (
SELECT VisitN.GID
FROM VisitN
WHERE VisitN.Vdate = '15-JUN-20' AND VisitN.restID IN (
SELECT RestaurantN.Restid
FROM RestaurantN having count(*)>2));
The table RestaurantN is not needed since you have restID in the table VisitN and you are not interested in the restaurant'a name, but only on their number.
Join GuestN to VisitN, aggregate and set the condition in the HAVING clause:
SELECT g.GID, g.Gname
FROM GuestN g INNER JOIN VisitN v
ON v.GID = g.GID
WHERE v.Vdate = '15-JUN-20'
GROUP BY g.GID, g.Gname
HAVING COUNT(DISTINCT v.restID) > 2

writing sql to find aggregation

I have these relations
Entry
-----
id
creationdate
grade
Subject
------
id
name
and join table
Entry_Subjects
------------
entry_id
subject_id
I need to create the sql to find average grade of entries belonging to a particular subject ( say 'java') on a particular creationdate
I tried the following
assume id for Subject 'java' is 2
SELECT creationdate,
avg(grade)
FROM (SELECT *
FROM Entry
WHERE id IN
(SELECT id
FROM Entry_Subjects
WHERE subject_id =2
)
)
GROUP BY creationdate;
I get the error
subquery in FROM must have an alias
I tried to correct this but couldn't
can somebody tell me why this error occurs.. my db knowledge is not that good
Probably want JOINs instead of nested SELECTs.
SELECT
creationdate,
AVG(grade)
FROM Entry e
INNER JOIN Entry_Subjects f
ON e.id = f.entry_id
INNER JOIN Subject s
ON f.subject_id = s.id
WHERE s.name = 'java' --this is where you replace 'java' with a variable to search by name
GROUP BY creationdate
Can also be done using analytical functions
select a.creationdate,avg(a.grade) over (partition by a.creationdate order by a.creationdate) as avg_grade
from entry a,subject b,entry_subjects c
where a.id=c.entry_id and b.id=c.subject_id
and upper(b.name)='JAVA';

How to write query in the following case?

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

Limiting recursion to certain level

I have a SQL table named Player and another called Team.
Each Player MUST belong to a team via a foreign key TeamID.
Each Team can belong to another Team via a recursive field ParentTeamID.
So it could be (top down)...
TeamA
TeamB
Team76
Group8
Player_ME
My question is, if I'm given a Player's PlayerID (the PK for that table), what is the best way to get the top Team?
My query so far (which gets all teams):
WITH TeamTree
AS (
SELECT ParentTeam.*, Player.PlayerID, 0 as Level
FROM Team ParentTeam
INNER JOIN Player ON Player.TeamID = ParentTeam.TeamID
WHERE Player.PlayerID IN (SELECT * FROM dbo.Split(#PlayerIDs,','))
UNION ALL
SELECT ChildTeam.*, TeamTree.PlayerID AS PlayerID, TeamTree.Level + 1
FROM Team ChildTeam
INNER JOIN TeamTree TeamTree
ON ChildTeam.TeamID = TeamTree.ParentTeamID
)
Now whilst I think this is the right place to start I think there may be a better way. Plus I'm kinda stuck! I tried using Level in a join (inside a subquery) but it didn't work.
Any ideas on how to work my way up the tree and get only the top level details?
Edit:
A ParentTeam CAN be a ParentTeam (infinite recursion), but a Player can only belong to one Team.
Data Structure
Team:
TeamID (PK), Name, ParentTeamID (Recursive field)
Player:
PlayerID (PK), Name, TeamID (FK)
Sample Data:
Team:
1, TeamA, NULL
2, TeamB, 1
3, Team76, 2
4, Group8, 3
Player:
1, Player_ME, 4
2, Player_TWO, 2
So with the above data, both players should show (in the query) that they have a "TopLevelTeam" of TeamA
I believe this is what you are looking for, with a bit of extra info thrown in for free :-)
Andrew had the correct idea in his edited version, but I think his implementation is incorrect.
The schema and query are available at SQL Fiddle
with teamCTE as (
select TeamID,
TeamName,
cast(null as int) as ParentTeamID,
cast(null as varchar(10)) as ParentTeamName,
TeamID TopTeamID,
TeamName TopTeamName,
1 as TeamLevel
from team
where ParentTeamID is null
union all
select t.TeamID,
t.TeamName,
c.TeamID,
c.TeamName,
c.TopTeamID,
c.TopTeamName,
TeamLevel+1 as TeamLevel
from team t
join teamCTE c
on t.ParentTeamID = c.TeamID
)
select p.PlayerID,
p.PlayerName,
t.*
from player p
join teamCTE t
on p.TeamID = t.TeamID
EDIT - answer to question in comment
You can navigate to any level within the player's team hierarchy simply by joining to the CTE a 2nd time. In your case you asked for the 2nd top most team: SQL Fiddle
with teamCTE as (
select TeamID,
TeamName,
cast(null as int) as ParentTeamID,
cast(null as varchar(10)) as ParentTeamName,
TeamID TopTeamID,
TeamName TopTeamName,
1 as TeamLevel
from team
where ParentTeamID is null
union all
select t.TeamID,
t.TeamName,
c.TeamID,
c.TeamName,
c.TopTeamID,
c.TopTeamName,
TeamLevel+1 as TeamLevel
from team t
join teamCTE c
on t.ParentTeamID = c.TeamID
)
select p.PlayerID,
p.PlayerName,
t1.*,
t2.TeamID Level2TeamID,
t2.TeamName Level2TeamName
from player p
join teamCTE t1
on p.TeamID = t1.TeamID
join teamCTE t2
on t1.TopTeamID = t2.TopTeamID
and t2.TeamLevel=2
WITH TeamTree
AS (
SELECT ParentTeam.*, Player.PlayerID AS UrPlayerID, 0 as Level
FROM Team ParentTeam
INNER JOIN Player ON Player.TeamID = ParentTeam.TeamID
WHERE Player.PlayerID IN (SELECT * FROM dbo.Split(#PlayerIDs,','))
UNION ALL
SELECT ChildTeam.*, TeamTree.PlayerID AS PlayerID, TeamTree.Level + 1
FROM Team ChildTeam
INNER JOIN TeamTree TeamTree
ON ChildTeam.ParentTeamID = TeamTree.TeamID /* These were reversed, I think */
AND UrPlayerID=ChildTeam.PlayerID /* ADDED */
)
Otherwise you get a huge duplication of rows, something like the square of the number of players, don't you?
--
(After comment below)
Quite right, I misread the schema. Look, you don't need to bring the player in until the very end. I thought the team tree arrangement might differ by player, but it doesn't. So
WITH recursive TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL;
This gives you a table of each team and its root ancestor. Now join that to the player table.
SELECT * FROM Player JOIN (WITH TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL) teamtree2
ON Player.TeamID=teamtree2.TeamID;
You can rejoin with Team if you need more columns.

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.