Count rows from LEFT JOIN where column is value - sql

I have teams, users, and points tables.
When I call get the teams from the database I need to also calculate the points as a generated column and also the number of users in that team as a new column.
I have this so far but it is returning all users in the member count column, not just the members in that team.
SELECT ar_teams.*, COALESCE(SUM(ar_points.amount),0) AS points, COUNT(ar_users.team_id) AS members
FROM ar_teams
LEFT JOIN ar_users ON ar_users.team_id = ar_teams.id
LEFT JOIN ar_points ON ar_points.user_id = ar_users.id
WHERE ar_teams.id = 1 AND ar_users.team_id = 1
GROUP BY ar_teams.id
The results I am getting:
id name name_alt points members
1 UK & Ireland NULL 3076 48
The members count should be 12, at the moment it seems to be counting all people without taking their team into account.

I suspect your problem is the use of count() rather than count(distinct). I think this is what you want:
SELECT ar_teams.*,
COALESCE(SUM(ar_points.amount), 0) AS points,
COUNT(distinct ar_users.id) AS members

Related

How to select all rows that are related to satisfied condition in ms ACCESS

I have the following data in table VehiclesAccSummary:
I am not sure how to do this but what I want is a query that would return all rows where there where only two car in the accident and it was a head on crash so in both cars PointOfImpact was 'Front' i know in need to do some inner join on the same table but i don' want to join same car with it self. Any idea ?
The end result should be something like this
You can use a subquery to count the number of "Front' records for each AccRef.
SELECT *
FROM VehiclesAccSummary INNER JOIN
(SELECT VehiclesAccSummary.AccRef, Count(VehiclesAccSummary.PointOfImpact) AS CountOfPointOfImpact FROM VehiclesAccSummary GROUP BY VehiclesAccSummary.AccRef, VehiclesAccSummary.PointOfImpact HAVING VehiclesAccSummary.PointOfImpact="Front") AS FrontCount
ON VehiclesAccSummary.AccRef = FrontCount.AccRef
WHERE VehiclesAccSummary.NumCars = 2 AND CountOfPointOfImpact = 2;
This will limit the records to AccRefs with NumCar = 2 and the count of Front records = 2.
Edit: Since the same car can be listed in multiple records, we need a new approach. Try this:
SELECT VehiclesAccSummary.*, Subquery.CountOfPointOfImpact
FROM VehiclesAccSummary LEFT JOIN (SELECT VehiclesAccSummary.AccRef, Count(VehiclesAccSummary.PointOfImpact) AS CountOfPointOfImpact
FROM VehiclesAccSummary
WHERE (((VehiclesAccSummary.PointOfImpact)<>"Front"))
GROUP BY VehiclesAccSummary.AccRef) AS Subquery ON VehiclesAccSummary.AccRef = Subquery.AccRef
WHERE (((Subquery.CountOfPointOfImpact) Is Null));
Instead of confirming that the count of front accidents is 2, this confirms that the count of non-front accidents is 0.

Is count() being used correctly for my query?

Find all teams that only won 1 game in tourney #3 (1 column, 4 rows)
My thought process to create this query is that I need to count (WonGame)s for each Team. And that that number cannot be has to equal 1. But When I run my query I get no results (I should get 4 teams).
Experimenting with my query I changed the equals to a greater than and that returned 8 results. So I don't understand why equals 1 returns no results.
Also I checked my Data and there is indeed 4 teams that one only one game during Tournament #3.
select Teams.TeamName
from Teams
join Bowlers on Teams.TeamID = Bowlers.TeamID
join Bowler_Scores on Bowlers.BowlerID = Bowler_Scores.BowlerID
join Match_Games on Bowler_Scores.GameNumber = Match_Games.GameNumber
join Tourney_Matches on Match_Games.MatchID = Tourney_Matches.MatchID
where Tourney_Matches.TourneyID = 3
group by Teams.TeamName
having count(Bowler_Scores.WonGame) = 1;
Bowling League DB Structure
Bowling League Data
The diagram seems to indicate that the relationship between Match_Games and Bowler_Scores is on BOTH of MatchID and GameNumber
If you change your JOIN conditions to be both columns
join Match_Games on Bowler_Scores.GameNumber = Match_Games.GameNumber and Bowler_Scores.MatchID = Match_Games.MatchID
Then you might get the required answer.
I can only speculate on what your data really looks like. However, it is doubtful that this expression:
having count(Bowler_Scores.WonGame) = 1;
does what you want. This counts the number of non-NULL values. Presumably, WonGame as some value such as "1" or "W" for the winner. If the value were 1, then the correct expression would be:
having sum(Bowler_Scores.WonGame) = 1
This is just speculation though without a better description of your data.
EDIT:
Based on the comment:
having sum(convert(int, Bowler_Scores.WonGame)) = 1

How can I select the highest counts attributes from different groups?

So I have a table with players data(name, team, etc..) and a table with goals (player who scored it, local team, etc...). What I need to do is, get from each team the highest scorer. So the result I'm getting is something like:
germany - whatever name - 1
germany - another dude - 5
spain - another name - 8
italy - one more name - 6
As you can see teams repeat, and I want them not to, just get the highest scorer of each team.
Right now I have this:
SELECT P.TEAM_PLAYER, G.PLAYER_GOAL, COUNT(*) AS "TOTAL GOALS" FROM PLAYER P, GOAL G
WHERE TO_CHAR(G.DATE_GOAL, 'YYYY')=2002
AND P.NAME = G.PLAYER_GOAL
GROUP BY G.PLAYER_GOAL, P.TEAM_PLAYER
HAVING COUNT(*)>=ALL (SELECT COUNT(*) FROM PLAYER P2 where P.TEAM_PLAYER = P2.TEAM_PLAYER GROUP BY P2.TEAM_PLAYER)
ORDER BY COUNT(*) DESC;
I am 100% sure I'm close, and I'm pretty sure I have to do this with the HAVING feature, but I can't get it right.
Without the HAVING it returns a list of all the players, their teams and how many goals have they scored, now I want to cut it down to only one player for each team.
PD: the teams in the table GOAL are local and visiting team, so I have to use the Player table to get the team. Also the Goal table is not a list of the players and how many goals they have scored, but a list of every individual goal and the player who scored it.
If I understand correctly you can try this query.
just get MAX of PLAYER_GOAL column,SUM(G.PLAYER_GOAL) instead of COUNT(*)
SELECT P.TEAM_PLAYER,
MAX(G.PLAYER_GOAL) "PLAYER_GOAL",
SUM(G.PLAYER_GOAL) AS "TOTAL GOALS"
FROM PLAYER P
INNER JOIN GOAL G
ON P.NAME = G.PLAYER_NAME
WHERE TO_CHAR(G.DATE_GOAL, 'YYYY')=2002
GROUP BY P.TEAM_PLAYER
ORDER BY SUM(G.PLAYER_GOAL) DESC;
NOTE :
Avoid using commas to join tables it's a old join style, You can use inner-join instead.
Edit
I don't know your table schema, but this query might be work.
use a subquery to contain your current result set. then get MAX function and GROUP BY
SELECT T.TEAM_PLAYER,
T.PLAYER_GOAL,
MAX(TOTAL_GOALS) AS "TOTAL GOALS"
FROM
(
SELECT P.TEAM_PLAYER, G.PLAYER_GOAL, COUNT(*) AS "TOTAL_GOALS" FROM
PLAYER P, GOAL G
WHERE TO_CHAR(G.DATE_GOAL, 'YYYY')=2002
AND P.NAME = G.PLAYER_GOAL
GROUP BY G.PLAYER_GOAL, P.TEAM_PLAYER
HAVING COUNT(*)>=ALL (SELECT COUNT(*) FROM PLAYER P2 where P.TEAM_PLAYER = P2.TEAM_PLAYER GROUP BY P2.TEAM_PLAYER)
) T
GROUP BY T.TEAM_PLAYER,
T.PLAYER_GOAL
ORDER BY MAX(TOTAL_GOALS) DESC

Join Queries with parameter filter on second query SSMS

I have two tables: EQUIPMENT and WORKORDERS.
EQUIPMENT returns the count of Equipment against a particular depot by the type of Equipment:
MAINTDEPOT EQUIPCOUNT EQUIPTYPE
1 44 MC
2 20 MC
3 5 MC
1 20 FS
2 3 FS
3 10 FS
...and so on. These counts rarely change unless a new bit of kit is put in.
I need to join a count of WORKORDERS to this table, but the work orders have a COSTCENTRE of either A B or E. This is so that I can generate a percentage of equipment with workorders.
I've joined the tables, but when I add a parameter filter to the WORKORDERS COSTCENTRE column the Count of EQUIPMENT changes, and I need it to stay the same.
I'm guessing I need to use subqueries to ensure that the left subquery remains static whilst the filter only changes the right hand one. Does anyone have any idea how I do this?
Here's my current query:
SELECT E.E_MAINTDEPOT, E.E_EQUIPCOUNT, C.Category, E.MYORDER, E.W_WORKCOUNT,
E.E_NOWO, E.W_HRS, E.E_QA, E.E_EGI, E.E_CLASS,
ISNULL(ROUND(CAST(E.E_NOWO AS Float) /
CAST(E.E_EQUIPCOUNT AS Float) * 100, 2), 100) AS RESULT,
SUBSTRING(E.E_CLASS, 1, 1) AS EM_CLASS
FROM (
SELECT T.E_MAINTDEPOT, COUNT(T.EQUIP_NO) AS E_EQUIPCOUNT,
SUM(C.W_WORKCOUNT) AS W_WORKCOUNT,
COUNT(T.EQUIP_NO) - SUM(C.W_WORKCOUNT) AS E_NOWO, T.MYORDER,
T.E_QA, T.E_EGI, T.E_CLASS, SUM(C.W_HRS) AS W_HRS
FROM EQDType AS T
FULL OUTER JOIN EquipWOCount AS C
ON T.EQUIP_NO = C.EQUIP_NO
GROUP BY T.MYORDER, T.E_MAINTDEPOT, T.E_QA, T.E_EGI, T.E_CLASS, C.W_FUNCTION
) AS E
INNER JOIN EQDCategory AS C
ON E.MYORDER = C.Myorder
ORDER BY E.MYORDER, E.E_MAINTDEPOT
Thank you

Several inner joins producing too many rows

I'm working on a field trip request software for school districts.
Each field trip has an account attached to it that will be billed. It will also have one or more driver/vehicle combinations and mileage and driver rates associated with each driver/vehicle combination.
I'm working on an accounting report that will show, by account, a count of the trips that are assigned to that account, the total number of miles driven on that account times a certain charge basis, and a total number of hours each driver has driven on that trip multiplied by their payrate.
I have a field trip (tripid=1) with two vehicles and two drivers and I expect two rows of output. However, I am getting 4 rows; Two rows for vehicle 81 and two rows for vehicle 56. Is there something in my joins that's causing too many rows to be outputted?
What's weird is Mister Driver is on both vehicles in the output of my query and so is Generic Person.
select distinct
tdv.tripid as tripid,
ta.name as account,
cb.chargebasisname as trip_type,
cb.defaultdistancerate as distance_rate,
(tc.odometerreturn-tc.odometerstart) as total_miles,
datediff(hour, tc.actualoriginstarttime,tc.actualoriginreturntime) as total_hours,
v.vehicle,
pr.hourlyrate as driver_rate,
e.firstname+' '+e.lastname as driver
from trip_tripdrivervehicle tdv
join trip_tripinformation ti
on ti.recordid = tdv.tripid
join trip_transportationaccounts ta
on ta.recordid = ti.accountid
join trip_invoicechargebasis cb
on cb.recordid = ta.defaultchargebasisid
join trip_tripcompletion tc
on tc.tripid = ti.recordid
join vehicles v
on v.recordid = tc.vehicleid
join trip_employeejobcategorypayrate pr
on pr.employeeid = tdv.driverid
join employees e
on e.recordid = tdv.driverid
where ti.triprequeststatusid = 7 and ti.recordid = 1
Here is my output:
https://lh6.googleusercontent.com/_Bbr20KcwLyw/TX5cwDhr7BI/AAAAAAAAbYE/qCfQtk6Xmeg/s800/sql_results.jpg
Looks like you also have two matches for the JOIN with table trip_tripcompletion - one that gives rows with total miles of 10 and another that gives rows with total miles of 50.
So each driver shows up with each total_miles option.
The JOIN condition for this table may need to be changed, or you can use GROUP BY along with MAX/MIN to show only the shortest/longest trip (depending on the need).