SQL query to add points from two tables within a database - sql

I'm about to have a cow here. I'm designing a hockey pool database, which at the moment consists of 3 tables as follows:
Table 1 Table 2 Table 3
TeamID TeamName GoalieID TeamID Points SkaterID TeamID Points
1 Marlies 1 1 10 1 4 20
2 Colts 2 3 5 2 1 25
3 Sting 3 2 6 3 3 7
4 Steelheads 4 4 7 4 2 12
The actual tables have a lot more players and teams, this is just an example.
I'm looking to create a query that will combine points totals for each player from Table2 and Table3, and display this information right next to the Team Name.
Team Name Total Points
Steelheads 27
Marlies 25
Colts 18
Sting 12
I have no problems summing points from a single table but unfortunately I'm having trouble wrapping my head around combining points that span across multiple tables. Could someone point me in the right direction please?

Do a UNION ALL in a derived table (p) to get all players at once, including goalies. LEFT JOIN with that result to get all teams with players' points. Finally do a GROUP BY and sum the points.
SELECT t1.TeamName, sum(p.Points) as TotalPoints
FROM Table1 t1
LEFT JOIN (select TeamID, Points from Table2
union all
select TeamID, Points from Table3) p
ON t1.TeamId = p.TeamId
GROUP BY t1.TeamName
(Have you considered to have all players in the same table?)

SELECT
Table1.TeamName,
sum(isNull(Table2.Points,0) + isNull(Table3.Points,0)) as TotalPoints
FROM
Table1
LEFT JOIN Table2
ON Table1.TeamId = Table2.TeamId
LEFT JOIN Table3
ON Table1.TeamId = Table3.TeamId
GROUP BY
Table1.TeamName

Related

Selecting all rows from t1 join t2 on id and select the lowest value from t2 or null if not any

I have two tables, one holds some categories and the other holds players' records like so:
Categories Times
id Name id UserId MapId CategoryId Time
1 cat1 1 1 1 1 1500
2 cat2 2 3 1 2 3000
3 cat3 3 13 1 3 2500
4 cat4 4 12 1 4 1500
5 cat5 5 11 1 4 1000
I want to select all the categories (id, name) and the lowest time on each category.
If there's no record on that category it should show NULL or 0.
This would be the expected result:
Result
id Name Time
1 cat1 1500
2 cat2 3000
3 cat3 2500
4 cat4 1000
5 cat5 0
I'm using the following query, but it only selects the categories that already have a record in Times.
For example, if I use the following query it'll not select 'cat5' because it doesn't have any record in table Times.
select t2.id, t2.Name, min(t1.Time) as Time
from Times t1
join Categories t2 on t2.id = t1.CategoryId
where t1.MapId = %MAPID%
group by t2.id
I recommend to begin your query with the table "categories" in this case since your focus is on the data from this table. So you could write a left join. Furthermore, I think it's a good idea to replace null values by zero, thus your query would as example find negative times as the lowest times and return 0 if the lowest time is a null value.
Overall, this could be your goal:
SELECT c.id, c.name, MIN(COALESCE(t.time,0)) AS time
FROM categories c LEFT JOIN times t ON c.id = t.categoryid
GROUP BY c.id, c.name;
Here is a working example according to your sample data: db<>fiddle
There are likely also other options to achieve your goal, you can just try out.
I think you might just need to do a right join (because you want all rows from the 2nd table listed -- Categories). See if you get the desired results by changing line 3 to be:
right join Categories t2 on t2.id = t1.CategoryId

SQL select with three tables and foreign keys

I have three tables :
field:
f_id
f_start
f_end
1
10
20
2
15
25
3
5
10
person :
p_id
p_name
1
Roger
2
John
3
Alicia
affect :
id
fk_field
fk_person
1
2
1
2
1
2
3
3
3
And I would like to select the dates and the names associated to. Like this
p_name
f_start
f_end
Roger
15
25
John
10
20
Alicia
5
10
I'm new to SQL and I don't know if i have to use JOIN or not... Thanks
You must join all 3 tables on their related columns:
SELECT p.p_name, f.f_start, f.f_end
FROM person p
INNER JOIN affect a ON a.fk_person = p.p_id
INNER JOIN field f ON f.f_id = a.fk_field;
Depending on your requirement you may need LEFT instead of INNER joins, but for this sample data the INNER joins will do.

JOIN functionality between multiple tables

Tables:
Client
CID Name
1 A
2 B
3 C
4 D
5 E
6..(And so on)
Visit
VID CID type
1 1 Med
2 3 Non
3 2 Non
4 6 Med
5 4 Med
6..(And so on)
Payment
PID CID amount
1 1 10
2 1 20
3 2 30
4 2 40
5 3 50
6..(And so on)
Desired Output:
CID Name type amount
1 A Med 10
1 A Med 20
4 D Med NULL
(And so on..)
Query:
SELECT DISTINCT
C.client_id
,C.name
,V.type
,P.payment
FROM Clients C
INNER JOIN Visit V
ON C.cid=V.cid
LEFT JOIN Payment P
ON V.cid=P.cid
I used a LEFT JOIN because I wanna see who made payments and who didn't.
Question: Do LEFT JOINS (or outer joins) pull in data based on the common id's in the CID of the left table resulting from preceding INNER JOINS(The common result set)? Or do they consider ALL the id's in the left table and ignore the INNER JOINS results altogether?
I only want payment details of the clients existing in the inner joins and not outside it.
The LEFT JOIN will only run on rows that the INNER JOIN returns, or the common data set as you mention.
That is regardless of what the LEFT JOIN will return, the INNER JOIN is going to limit the result set based on Visit V ON C.cid=V.cid
This venn diagram shows the results that will be selected, the blue area is your data that will be returned. The order of the joins does not matter.

SQL: CUSTOMER that has bought a WORK from every ARTIST || 2 tables

So I have 2 tables that both contain IDs
work:
workID, artistID
1 6
2 7
3 8
4 6
5 6
trans:
CustomerID, workID
10 1
11 2
12 3
10 4
10 5
So far I've only managed to put all the ID's together but the result I need is to show any customerID that has purchased a workID from every artistID:
SELECT
trans.customerID, trans.workID, work.artistID
FROM
trans
INNER JOIN work
ON trans.workID=work.workID
WHERE
trans.customerID IS NOT null
ORDER BY
trans.customerID;
Basically I have no idea what my next step should be, if anyone could point me in the right direction or explain a solution that would be great.
EDIT: added simplified data to tables
This should get you going:
SELECT t.customerId
FROM
( SELECT t.CustomerId, COUNT(DISTINCT artistId) as artists
FROM trans t INNER JOIN work w ON w.workid = t.workid) t
INNER JOIN
( SELECT COUNT(DISTINCT artistId) artists FROM work) a ON t.artists = a.artists

How to count linked entries in another table with a specific value

Let's say I have two tables. A students table and an observations table. If the students table looks like:
Id Student Grade
1 Alex 3
2 Barney 3
3 Cara 4
4 Diana 4
And the observations table looks like:
Id Student_Id Observation_Type
1 1 A
2 1 B
3 3 A
4 2 A
5 4 B
6 3 A
7 2 B
8 4 B
9 1 A
Basically, the result I'd like from the query would be the following:
Student Grade Observation_A_Count
Alex 3 2
Barney 3 1
Cara 4 2
Diana 4 0
In other words, I'd like to gather data for each student from the students table and for each student count the number of A observations from the observations table and tack that onto the other information. How do I go about doing this?
This is a simple join and aggregate:
select
a.Student,
a.Grade,
count(b.Id) as Observation_A_Count
from
Student a left join
Observations b on a.Id = b.Student_Id
group by
a.Student,
a.Grade
order by
1
Or, you can use a correlated subquery:
select
a.Student,
a.Grade,
(select count(*) from observations x where x.Student_Id = a.Id) as Observation_A_Count
from
Student a
order by
a.Student
You can join the table with a specific condition, by doing this you can have a field for Observation_B_Count and Observation_C_Count, etc.
SELECT Student.Student, Student.Grade, COUNT(Observation_Type.*) AS Observation_A_Count
FROM Student
LEFT JOIN Observations ON Observations.Student_ID = Student.Student_ID AND Observations.Observation_Type = 'A'
GROUP BY Student.Student, Student.Grade