SQL complicated join query - mysql

I have two tables: match(id.match, date, home, away) and team(id. team, name). In match home and away are foreign keys to the team id. In my query, I want an output record with date of match, and name of these two teams.
I have tried:
SELECT m.date, m.home, m.away, t.name
FROM `match` m
JOIN team t ON m.home = t.id_team
ORDER BY m.date
But this outputs two records instead of one. Is it possible to do what I want with sql or I should just change the table's design?

I suspect you have a many to one relationship between your tables.
This might work depending on the table values:
SELECT DISTINCT m.date, m.home, m.away, t.name
FROM `match` m JOIN
team t ON m.home = t.id_team
ORDER BY m.date

Ok, i did 'deeper' research and find out the answer. Earlier i just asked wrong question. Thanks everyone for contribution!
Here is the solution:
SELECT m.date, m.home, m.away, t.name AS homename, te.name AS awayname
FROM `match` m
JOIN team t ON m.home = t.id_team
JOIN team te
ON m.away = te.id_team ORDER BY m.date

Related

How to find the number of Distinct ID's on one table

SELECT Count(Teams.Name)
, Teams.TeamID
, Teams.Name
FROM Teams, Rosters
WHERE Rosters.TeamID = Teams.TeamID
Is my query so far. I'd like it to print the number of entries of Rosters.TeamID that correspond to Teams.TeamID.
I think the query you want is:
SELECT t.TeamID, t.Name, COUNT(*)
FROM Teams t JOIN
Rosters r
ON r.TeamID = t.TeamID
GROUP BY t.TeamID, t.Name;
Basically, your query is missing the GROUP BY, but you should also learn proper JOIN syntax.

I am unsure: Is this an anti-join?

I am working on the first problem of the famous SQLzoos and am working on the using Null section: http://sqlzoo.net/wiki/Using_Null
The question is:
List the teachers who have NULL for their department.
The corresponding SQL query would be:
SELECT t.name
FROM teacher t
WHERE t.dept IS NULL
Is this a type of anti-join? Specifically, is this a left-anti-join?
This isn't a join at all.
The statement is filtering only records for teachers who don't have an assigned department.
Set Difference
The set difference of teachers and departments, teacher \ department would be a kind of "anti-join"
SELECT
t.name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL
At first glance, this statement does what your statement does, if the foreign key reference was enforced, it would guarantee to do exactly that. However, one use for this statement would be to retrieve teachers who are assigned to departments that have since been deleted (e.g. if the English Lit Dept. & English as 2nd Lang Dept. were reorganized as the English Dept.)
Symmetric Difference
Another "anti-join" would be the symmetric difference, which selects elements from both sets ONLY if they cannot be joined, i.e
(teacher \ department) U (department \ teacher)
I can't think of a motivating example using teachers and departments, but one way to write the symmetric difference on databases that support the FULL OUTER JOIN would be:
SELECT
t.name
FROM teacher t
FULL OUTER JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL OR t.id IS NULL
For MySQL, this statement would have to be written as the union of two statements.
SELECT
t.name teacher_name, d.name department_name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE d.id IS NULL
UNION ALL
SELECT
t.name teacher_name, d.name department_name
FROM teacher t
LEFT JOIN department d ON d.id = t.dept_id
WHERE t.id IS NULL
Looking through one of my projects, I found this one use of symmetric difference:
Context:
I have three tables: users, users_gameplay_summary, users_transactions_summary. I needed to email those users who created their accounts in the past 7 days AND one of the following
have transacted but have not played or played but have not transacted.
To get the list, I have this query (note, this was written for Postgresql, and won't work on MySQL, but it illustrates the symmetric difference use case):
SELECT
COALESCE(g.user_id, t.user_id) user_id
FROM users_gameplay_summary g
FULL OUTER JOIN users_transactions_summary t ON t.user_id = g.user_id
WHERE COALESCE(g.user_id, t.user_id) IN (
SELECT user_id
FROM users
WHERE created_at > CURRENT_DATE - '7 day'::interval)
AND (g.user_id IS NULL OR t.user_id IS NULL)
Not exactly, your not actually joining anything now,
in the case of a left anti join you would have access to the department name as well. (although it would be NULL)
Your sql code would be a correct answer for the question you gave though.
A left anti join would be:
SELECT t.name
FROM teacher t
LEFT JOIN dept d ON d.id = t.dept
WHERE d.id IS NULL
To solve this problem of listing teachers without assigned departments, you don't need a JOIN between teacher and dept tables.
dept table is basically a dictionary table that you join to, to translate ids to corresponding names.
teacher table has a dept column which normally could have a FOREIGN KEY constraint to id column in dept table.
Your query is not an ANTI-JOIN. This is a simple projection and selection query using one table.
SELECT t.name
FROM teacher t
WHERE t.dept IS NULL
For an ANTI-JOIN you would at least need a JOIN operation between more than one table at first.
Normally an ANTI-JOIN could look like:
Using LEFT JOIN
SELECT *
FROM table1 t1
LEFT JOIN table2 t2
ON t1.join_column = t2.join_column
WHERE t2.join_column IS NULL
Using NOT EXISTS
SELECT *
FROM table1 t1
WHERE NOT EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.join_column = t2.join_column
)

3 table query with count

I'm having huge difficulty with a 3 table query.
The scenario is that TEAM has many or no MEMBERS, a MEMBER could have many or no TASKS. What I want to get is the number of TASKS for every TEAM. TEAM has its own ID, MEMBER holds this as a FK on TEAM_ID, TASK has MEMBER_ID on the TASK.
I want to get a report of TEAM.NAME, COUNT(Person/Team), Count(Tasks/Team)
I have myself so confused, My thinking was to use an Outer Join on TEAM and MEMBER so I have all the teams with any members they have. From here I'm getting totally confused. If anyone can just point me in the right direction so I have something to work from I'd be so greateful
You want to use count distinct:
MySQL COUNT DISTINCT
select t.name as Team,
count(distinct m.ID) as Member_cnt,
count(distinct t.ID) as Task_cnt
from team t
left join member m
on t.ID= m.TEAM_ID
left join tasks t
on t.MEMBER_ID= m.ID
group by t.name;
I think you can do what you want with aggregation -- and count(distinct):
select t.name,
count(distinct m.memberid) as nummembers,
count(distinct tk.taskid) as numtasks
from team t left join
member m
on t.teamid = j.teamid left join
tasks tk
on tk.memberid = m.memberid
group by t.name;
Try this out :
SELECT Team.name, COUNT(Person.id_person), COUNT(Tasks.id_task)
FROM Team t,
LEFT JOIN Person p on p.team_id = t.id_team
LEFT JOIN Tasks ts on ts.person_id = p.id_person
GROUP BY p.team_id, ts.person_id

How do I finish of this SQL query

It works but what I would like is to list username, first name, last name not all but I've tried JOIN and isn't seeming to work. Any ideas? Thanks!
MY DB:
http://gyazo.com/eb13cd68440d20719ce0783018cb9828
SELECT
M.Username,
M.first_name,
M.Last_name,
COUNT(1) AS num_comments
FROM members AS M
INNER JOIN comments AS C
ON C.memberID = M.memberID
GROUP BY
C.memberID
ORDER BY COUNT(1) DESC
LIMIT 1
This matches the Member to all their comments, groups by the member to get the count of comments for the users, orders by the count starting highest first, then returns the first result.
Instead of selecting * (ALL) just use SELECT table.username, table.firstname, table.lastname [...].
You can leave out the table. if all information is stored in your comments table. If not, adjust accordingly. In that case you'll also need to Join the comments table with the table where the rest of the information is stored.
Edit:
SELECT m.username, m.first_name, m.last_name FROM members m, comments c WHERE m.MemberID = c.MemberID AND c.author = (select max(author) from comments)

MySQL join strange results

Can anyone help, mysql is beyond me I think!
I have the following tables:
matches
teams
competition
matches holds the details of a game between two teams and the corresponding competition.
I want to query the data base for all games/fixtures for a given competition, I want to return:
team names
team id
team competition
Here is my query:
SELECT
matches.match_id,
teamsh.team_name AS "homeTeam",
teamsa.team_name AS "awayTeam",
competition.competition_id,
competition.name
FROM
matches, teams teamsh, teams teamsa, competition
WHERE
matches.home_team_id = teamsh.team_id
AND matches.away_team_id = teamsa.team_id
AND matches.competition_id=2
For some reason this query returns all fixtures correctly for competition 2, but then it also returns rows for the fixture but as competition 1 also. I can't understand why as I have the clause:
AND matches.competition_id=2
What am I doing wrong, I have checked the database and the matches are stored correctly for each fixture.
Thanks.
You haven't explicitly linked to the competition table (so it's performing a cartesian join) - try adding:
and matches.competition_id = competition.competition_id
- to the end of your query.
Although, I would suggest rewriting the query to use the explicit join syntax - like so:
SELECT m.match_id,
h.team_name AS "homeTeam",
a.team_name AS "awayTeam",
c.competition_id,
c.name
FROM matches m
JOIN teams h ON m.home_team_id = h.team_id
JOIN teams a ON m.away_team_id = a.team_id
JOIN competition c ON m.competition_id = c.competition_id
WHERE m.competition_id=2
You forgot the JOIN condition between the competitions and matches tables.
WHERE
matches.home_team_id = teamsh.team_id
AND matches.away_team_id = teamsa.team_id
AND matches.competition_id = competition.competition_id
AND matches.competition_id=2