Group by and Having aggregation - sql

i'm trying to determine who is the largest scorer in a world cup group (this is a personal project)
I have the data but i'm having a hard time using count, group by and having in order to accomplish what i need.
I need to count messi's goals (top scorer) and group by each one of the groups so i get the highest scorer of each group.
For now i just have the joins:
select * from zonas
left join goles_zonas on (zonas.id = goles_zonas.Id_zona)
inner join goles on (goles.id = goles_zonas.id_gol)
inner join jugadores on (goles.id_jugador = jugadores.id)

instead displaying all columns (by using SELECT * ), in order to group the data, I find it necessary to do SELECT only certain columns which are considered to be the keys to determine the difference of each group of dataset to get the aggregation (in this case COUNT) of each dataset group
SELECT Id_zona, id_gol, id_jugador, COUNT(1) as number_of_goal
FROM zonas
left join goles_zonas on (zonas.id = goles_zonas.Id_zona)
inner join goles on (goles.id = goles_zonas.id_gol)
inner join jugadores on (goles.id_jugador = jugadores.id)
GROUP BY Id_zona, id_gol, id_jugador
It has to be grouped by all columns included the select statement that does not being aggregated.
but if you expect to display other columns as well which are not part of the grouping keys, you can do it like this
SELECT goles_zonas.* , x.* FROM (
SELECT Id_zona, id_gol, id_jugador, COUNT(1) as number_of_goal
FROM zonas
left join goles_zonas on (zonas.id = goles_zonas.Id_zona)
inner join goles on (goles.id = goles_zonas.id_gol)
inner join jugadores on (goles.id_jugador = jugadores.id)
GROUP BY Id_zona, id_gol, id_jugador ) X
LEFT JOIN goles_zonas on (x.id = goles_zonas.Id_zona)

Related

how can I get the selected columns fully and the sum column separately

SELECT f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id,date,sum(payments.paid_amount)
FROM payments
LEFT JOIN family ON family.id = payments.family_id
LEFT JOIN teachers ON family.teacher_id = teachers.t_id
How can I get the selected columns fully and the sum column separately?
because that sum function makes all the selected result one row
SELECT f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id,date
FROM payments
LEFT JOIN family ON family.id = payments.family_id
LEFT JOIN teachers ON family.teacher_id = teachers.t_id
This query is working fine without the sum column
You didn't tell the database, which column to use for aggregating the data. Don't know which database you are using, but some complain, that there is no GROUP BY statement in the SQL text.
Please try with the following query:
SELECT f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id,date,sum(payments.paid_amount)
FROM payments
LEFT JOIN family ON family.id = payments.family_id
LEFT JOIN teachers ON family.teacher_id = teachers.t_id
GROUP BY f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id,date
GROUP BY tells the database, which are the key columns in the aggregation.
If you want all the payments, use a subquery or join:
SELECT f_name, l_name, t.first_name, t.t_id, p.p_id, p.paid_amount, p.family_id, date,
(select sum(p.paid_amount) from payments) as all_paid
FROM payments p LEFT JOIN
family f
ON f.id = p.family_id LEFT JOIN
teachers t
ON f.teacher_id = tetchers.t_id;
SELECT f_name,l_name,t.first_name,t.t_id,p_id,paid_amount,family_id,date,sum(p.paid_amount)
FROM payments p,family f,teachers t where f.id = p.family_id and f.teacher_id = t.t_id
Group by f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id
You can add date column also in Group by expression based on your requirement. Example:
f_name,l_name,teachers.first_name,teachers.t_id,p_id,paid_amount,family_id,date

How to use coalesce with pivot

Hello I'm trying to figure out to use coalesce with a Pivot so I can replace the NULLS with zeroes instead. Here is what I have:
SELECT * FROM ( SELECT MovieTitle,AwardResultDesc, COALESCE(COUNT(p.AwardResultID),'0') AS T
FROM tblMovie t1
INNER JOIN tblAwardDetail p
ON p.MovieID = t1.MovieID
INNER JOIN tblAwardResult c
ON c.AwardResultID = p.AwardResultID
GROUP BY MovieTitle, AwardResultDesc,p.AwardResultID)
PIVOT
(
max(T) FOR AwardResultDesc IN ('Won' AS "Won",'Nominated' AS "Nominated")
)
ORDER BY MovieTitle;
It seems like my Pivot is ignoring my coalesce for some reason, any suggestions?
By their nature pivot operations involve aggregate functions, so there's no need to pre-aggregate your data, however, you do need to ensure that the data you are pivoting is sufficiently complete. Here outer joining to tblMovie ensures each movie is returned whether it has any award details or not. If you don't want to return counts for movies that neither won nor received nominations, then use an inner join in place of the outer join:
WITH dta AS (
SELECT MovieTitle
, AwardResultDesc
FROM tblAwardResult ar
JOIN tblAwardDetail ad
ON ad.AwardResultID = ar.AwardResultID
RIGHT JOIN tblMovie m
ON m.MovieID = ad.MovieID
)
SELECT *
FROM dta
PIVOT( count(*)
FOR AwardResultDesc IN( 'Won' AS "Won"
, 'Nominated' AS "Nominated" ) )
ORDER BY MovieTitle;

Matching two ID columns and return the most recent entry from a second table

I have 2 tables, both with a common ID column. The second table contains multiple rows matching the ID column in the first table, and I need to return the most recent entry from the second table. My solution below is almost correct, but it returns a single value across all ID columns, and not the value corresponding to that actual ID column.
As you can see, it is dealing with payments, so just need to return the date that the most recent payment covers.
(SELECT TOP 1CONVERT(VARCHAR,MemberPayments.CoverFinishDay,105)
FROM
Members LEFT JOIN MemberPayments
ON Members.MemberID = MemberPayments.MemberID
AND MemberPayments.CoverFinishDay = (
SELECT MAX(CoverFinishDay)
FROM MemberPayments
WHERE Members.MemberID = MemberPayments.MemberID
))
Any idea why it would just be returning one value across all?
Is this what you are looking for?
;WITH LatestMemPayments AS
(
SELECT MemberID
,CoverFinishDay = MAX(CoverFinishDay)
FROM MemberPayments
GROUP BY MemberID
)
SELECT *
FROM Members ME
JOIN LatestMemPayments MP ON ME.MemberID = MP.MemberID
Written as derived table instead of CTE;
SELECT *
FROM Members ME
JOIN (
SELECT MemberID
,CoverFinishDay = MAX(CoverFinishDay)
FROM MemberPayments
GROUP BY MemberID
) MP ON ME.MemberID = MP.MemberID
Potentially as a single query;
SELECT ME.Col1
,ME.Col2
,CoverFinishDay = MAX(MP.CoverFinishDay)
FROM Members ME
JOIN MemberPayments MP ON ME.MemberID = MP.MemberID
GROUP BY ME.Col1
,ME.Col2
Try this, it will find all information in MemberPayments for the latest data:
SELECT *
FROM
Members
OUTER APPLY
(SELECT top 1 *
FROM
MemberPayments
WHERE
Members.MemberID = MemberPayments.MemberID
ORDER BY
CoverFinishDay DESC) x
If you just need the latest date:
SELECT m.MemberID, m.Field2, m.Field3, max(mp.CoverFinishDay) as LatestDate
FROM
Members m
LEFT JOIN
MemberPayments mp
ON
Members.MemberID = MemberPayments.MemberID
GROUP BY m.MemberID, m.Field2, m.Field3

Left outer join and group by issue

I wrote a query. this query sum fields from 2 different table. And grouped by main table id field. But second left outer join is not grouped and giving me different results.
SELECT s.*,
f.firma_adi,
sum(sd.fiyat) AS konak,
sum(ss.fiyat) AS sponsor
FROM fuar_sozlesme1 s
INNER JOIN fuar_firma_2012 f
ON ( s.cari = f.cari )
LEFT OUTER JOIN fuar_sozlesme1_detay sd
ON ( sd.sozlesme_id = s.id )
LEFT OUTER JOIN fuar_sozlesme1_sponsor ss
ON ( ss.sozlesme_id = s.id )
GROUP BY s.id
ORDER BY s.id DESC
I know, it is really complicated but I'm stucking on this issue.
My question is: why second left outer join is not correctly sum of field . If I remove second left outer join or first, everything is normal.
The problem is that you have multiple dimensions on your data, and the number of rows is multiplying beyond what you expect. I would suggest that you run the query for one id, without the group by, to see what rows the join is producing.
One way to fix this is by using correlated subqueries:
select s.*, f.firma_adi,
(select SUM(sd.fiyat)
from fuar_sozlesme1_detay fd
where sd.sozlesme_id = s.id
) as konak,
(select SUM(ss.fiyat)
from fuar_sozlesme1_sponsor ss
where (ss.sozlesme_id = s.id)
) as sponsor
from fuar_sozlesme1 s inner join
fuar_firma_2012 f
on (s.cari = f.cari)
order by s.id DESC
By the way, you appear to by using MySQL (because your query is not parsable in any other dialect). You should tag your questions with the version of the database you are using.

i want to modify this SQL statement to return only distinct rows of a column

select
picks.`fbid`,
picks.`time`,
categories.`name` as cname,
options.`name` as oname,
users.`name`
from
picks
left join categories
on (categories.`id` = picks.`cid`)
left join options
on (options.`id` = picks.oid)
left join users
on (users.fbid = picks.`fbid`)
order by
time desc
that query returns a result that like:
my question is.... I would like to modify the query to select only DISTINCT fbid's. (perhaps the first row only sorted by time)
can someone help with this?
select
p2.fbid,
p2.time,
c.`name` as cname,
o.`name` as oname,
u.`name`
from
( select p1.fbid,
min( p1.time ) FirstTimePerID
from picks p1
group by p1.fbid ) as FirstPerID
JOIN Picks p2
on FirstPerID.fbid = p2.fbid
AND FirstPerID.FirstTimePerID = p2.time
LEFT JOIN Categories c
on p2.cid = c.id
LEFT JOIN Options o
on p2.oid = o.id
LEFT JOIN Users u
on p2.fbid = u.fbid
order by
time desc
I don't know why you originally had LEFT JOINs, as it appears that all picks must be associated with a valid category, option and user... I would then remove the left, and change them to INNER joins instead.
The first inner query grabs for each fbid, the FIRST entry time which will result in a single entity for the FBID. From that, it re-joins to the picks table for the same ID and timeslot... then continues for the rest of the category, options, users join criteria of that single entry.
2 options, you could write a group by clause.
Or you could write a nested query joined back to itself to get pertinent info.
Nested aliased table:
SELECT
n.fBids
FROM
MyTable t
INNER JOIN
(SELECT DISTINCT fBids
FROM MyTable) n
ON n.ID = t.ID
Or group by option
SELECT fBId from MyTable
GROUP BY fBID
select picks.`fbid`, picks.`time`, categories.`name` as cname,
options.`name` as oname, users.`name` from picks left join categories
on (categories.`id` = picks.`cid`) left join options on (options.`id` = picks.oid)
left join users on (users.fbid = picks.`fbid`)
order by time desc GROUP BY picks.`fbid`
select
picks.fbid,
MIN(picks.time) as first_time,
MAX(picks.time) as last_time
from
picks
group by
picks.fbid
order by
MIN(picks.time) desc
However, if you want only distinct fbid's you cannot display cname and other columns at the same time.