GROUP BY clause SQL invalid aggregate function - sql

I'm trying to group by 'Condicion' but it takes an error:
Column 'exercisepractice.Cantidad' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
What am I doing wrong here? I am getting this error on:
create view exercisepractice
as
select 'Aprobados' as Condicion, sum(case when Promedio>13.5 then 1 else 0 end) as 'Cantidad', A.Sexo
from vAlumnos A inner join vMatricula M
on(A.CodAlumno=M.CodAlumno)
inner join vNotas N
on (M.NroMatricula=N.NroMatricula)
where N.SemAcademico='2020-I'
GROUP BY A.Sexo
union all
select 'Aprobados' as Condicion, sum(case when Promedio>13.5 then 1 else 0 end) as 'Cantidad', A.Sexo
from vAlumnos A inner join vMatricula M
on(A.CodAlumno=M.CodAlumno)
inner join vNotas N
on (M.NroMatricula=N.NroMatricula)
where N.SemAcademico='2020-I'
GROUP by A.Sexo
union all
select 'Desprobados' as Condicion, sum(case when Promedio<13.5 then 1 else 0 end) as 'Cantidad', A.Sexo
from vAlumnos A inner join vMatricula M
on(A.CodAlumno=M.CodAlumno)
inner join vNotas N
on (M.NroMatricula=N.NroMatricula)
where N.SemAcademico='2020-I'
GROUP BY A.Sexo
union all
select 'Desaprobados' as Condicion, sum(case when Promedio<13.5 then 1 else 0 end) as 'Cantidad', A.Sexo
from vAlumnos A inner join vMatricula M
on(A.CodAlumno=M.CodAlumno)
inner join vNotas N
on (M.NroMatricula=N.NroMatricula)
where N.SemAcademico='2020-I'
GROUP by A.Sexo
select * from exercisepractice
GROUP by Condicion
My expected result is like this:
CONDICION
CANTIDAD
SEXO
Aprobados
XXXX
M
Aprobados
XXXX
F
Desaprobados
XXXX
M
Desaprobados
XXXX
F

LOL I was duplicating 'Approved' and 'Disapproved'

Related

using Query one results to run Query two

SELECT distinct
Pd.Cpd as ' accountnumber'
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
This code would result with this
Result
accountnumber
1332132
3213123
5641202
6412221
1233242
What I would like to do is when the code above gets the results my bottom code reads them and runs them trough its code. The common denominator here would be the account number because its running through a different table
SELECT
pm.AcctNumb as 'accountnumber'
, SUM(CASE WHEN pm.cusidIN ('cr') THEN 1 ELSE 0 END) AS CA
, SUM(CASE WHEN pm.cusidIN ('gb') THEN 1 ELSE 0 END) AS GB
, SUM(CASE WHEN pm.cusidIN ('tev','offev','Lastev') THEN 1 ELSE 0 END) AS chr
, SUM(CASE WHEN pm.cusidIN
('pm','pr','che' )
THEN 1 ELSE 0 END) AS Act
, SUM(CASE WHEN pm.cusidIN ('supev','tev') THEN 1 ELSE 0 END) AS Fulfillment
FROM ops.medadata pm WITH (NOLOCK)
INNER JOIN mw.pim_acct Ma with (nolock) ON ma.AcctNumb= pm.AcctNumb
Where pm.AcctNumb in ()
GROUP BY
pm.AcctNumb
I have tried doing this the code below but it doesnt seem to work
With counta as (
SELECT distinct
Pd.Cpd as ' accountnumber'
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
SELECT
pm.AcctNumb as 'accountnumber'
, SUM(CASE WHEN pm.cusidIN ('cr') THEN 1 ELSE 0 END) AS CA
, SUM(CASE WHEN pm.cusidIN ('gb') THEN 1 ELSE 0 END) AS GB
, SUM(CASE WHEN pm.cusidIN ('tev','offev','Lastev') THEN 1 ELSE 0 END) AS chr
, SUM(CASE WHEN pm.cusidIN
('pm','pr','che' )
THEN 1 ELSE 0 END) AS Act
, SUM(CASE WHEN pm.cusidIN ('supev','tev') THEN 1 ELSE 0 END) AS Fulfillment
FROM ops.medadata pm WITH (NOLOCK)
INNER JOIN mw.pim_acct Ma with (nolock) ON ma.AcctNumb= pm.AcctNumb
left join counta on Pm.accountnumber = counta.accountnumber
Where pm.AcctNumb in (counta.accountnumber)
GROUP BY
pm.AcctNumb
**im having issue with joining the two tables together**
IN is not an equivalent to a join - but you are treating that way.
Instead think of "IN this LIST" and the list could be supplied by you, or by a subquery e.g.
a list given by the query itself
select * from atable
where acol IN ('a','b','c') -- i.e. the list is hardcoded
or, using a subquery
SELECT ...etc.
WHERE pm.AcctNumb IN (
SELECT Pd.Cpd
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
or, if using a CTE
With counta as (
SELECT Pd.Cpd
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
SELECT ... etc.
WHERE pm.AcctNumb IN (
SELECT Cpd
FROM counta
)
note, it usually is not more efficient to use select distinct when forming a subquery to be used with an IN list.

SQL: Attribute matches two different conditions at the same time

I want to make a query where an attribute (same attribute) matches two different conditions at the same time. I have to check if a driver was found in both cities.
I tried to use intersect but I don't get any matches. But in my table I have one driver that matches this conditions.
SELECT s.NumeSofer
FROM Soferi s
INNER JOIN contraventii c ON s.idSofer=c.idSofer
INNER JOIN localitati l ON c.idLocContr=l.idLoc
WHERE l.DenLoc IN ('Iasi', 'Rosiori') AND l.Jud IN ('IS', 'NT');
INTERSECT
SELECT s.NumeSofer
FROM Soferi s
INNER JOIN contraventii c ON s.idSofer=c.idSofer
INNER JOIN localitati l ON c.idLocContr=l.idLoc
WHERE l.DenLoc='Rosiori' AND l.Jud='NT';
You can use aggregation and a HAVING clause, like:
SELECT s.NumeSofer
FROM Soferi s
INNER JOIN contraventii c ON s.idSofer=c.idSofer
INNER JOIN localitati l
ON c.idLocContr = l.idLoc
AND (l.DenLoc, l.Jud) IN ( ('Iasi', 'IS'), ('Rosiori', 'NT') )
GROUP BY s.NumeSofer
HAVING
MAX(CASE WHEN l.DenLoc = 'Iasi' AND l.Jud = 'IS' THEN 1 END) = 1
AND MAX(CASE WHEN l.DenLoc = 'Rosiori' AND l.Jud = 'NT' THEN 1 END) = 1
This will bring you all NumeSofer for which at least one record exists in localitati with DenLoc='Iasi' AND Jud='IS' and at least one record exists with DenLoc='Rosiori' AND Jud='NT'.
Note: the IN operator can be used with tuple values; this reduce the lenght of the query, while avoiding using OR, which is usually not good for general performance.
Do a GROUP BY instead. Use case expressions to do conditional aggregation:
SELECT s.NumeSofer, count(distinct l.DenLoc) as totcount,
count(case when l.DenLoc='Rosiori' then 1 end) as Rosioricount,
count(case when l.DenLoc='Iasi' then 1 end) as Iasicount
FROM Soferi s
INNER JOIN contraventii c ON s.idSofer=c.idSofer
INNER JOIN localitati l ON c.idLocContr=l.idLoc
WHERE (l.DenLoc='Rosiori' AND l.Jud='NT')
OR (l.DenLoc='Iasi' AND l.Jud='IS')
GROUP BY s.NumeSofer
ORDER BY totcount desc
Any rows with totcount = 2?
To get only drivers with both DenLoc's add a HAVING clause:
SELECT s.NumeSofer, count(distinct l.DenLoc) as totcount,
count(case when l.DenLoc='Rosiori' then 1 end) as Rosioricount,
count(case when l.DenLoc='Iasi' then 1 end) as Iasicount
FROM Soferi s
INNER JOIN contraventii c ON s.idSofer=c.idSofer
INNER JOIN localitati l ON c.idLocContr=l.idLoc
WHERE (l.DenLoc='Rosiori' AND l.Jud='NT')
OR (l.DenLoc='Iasi' AND l.Jud='IS')
GROUP BY s.NumeSofer
HAVING count(distinct l.DenLoc) > 1

SQL correct query or not

given these relationships, how could you query the following:
The tourists (name and email) that booked at least a pension whose rating is greater than 9, but didn't book any 3 star hotel with a rating less than 9.
Is the following correct?
SELECT Tourists.name, Tourists.email
FROM Tourists
WHERE EXISTS (
SELECT id FROM Bookings
INNER JOIN Tourists ON Bookings.touristId=Tourists.id
INNER JOIN AccomodationEstablishments ON Bookings.accEstId=AccomodationEstablishments.id
INNER JOIN AccomodationTypes ON AccomodationEstablishments.accType=AccomodationTypes.id
WHERE AccomodationTypes.name = 'Pension' AND
AccomodationEstablishments.rating > 9
) AND NOT EXISTS (
SELECT id FROM Bookings
INNER JOIN Tourists ON Bookings.touristId=Tourists.id
INNER JOIN AccomodationEstablishments ON Bookings.accEstId=AccomodationEstablishments.id
INNER JOIN AccomodationTypes ON AccomodationEstablishments.accType=AccomodationTypes.id
WHERE AccomodationTypes.name = 'Hotel' AND
AccomodationEstablishments.noOfStars = 3 AND
AccomodationEstablishments.rating < 9
)
I would do this using aggregation and having:
SELECT t.name, t.email
FROM Bookings b INNER JOIN
Tourists t
ON b.touristId = t.id INNER JOIN
AccomodationEstablishments ae
ON b.accEstId = ae.id INNER JOIN
AccomodationTypes a
ON ae.accType = a.id
GROUP BY t.name, t.email
HAVING SUM(CASE WHEN a.name = 'Pension' AND ae.rating > 9 THEN 1 ELSE 0 END) > 0 AND
SUM(a.name = 'Hotel' AND ae.noOfStars = 3 AND ae.rating < 9 THEN 1 ELSE 0 END)= 0;
Your method also works, but you probably need t.id in the subqueries.

Invalid column name error while using left join

I am getting Invalid column name 'PostId' error while executing the following query
Select a.SuburbDiscussionID,SUM((CASE WHEN b.postcnt IS NULL THEN 0 ELSE b.postcnt END) + (CASE WHEN c.replycnt IS NULL THEN 0 ELSE c.replycnt END)) AS TotCount
from SuburbDiscussions a
left join (SELECT COUNT(*) as postcnt,Posts.DiscussionId FROM Posts
GROUP BY Posts.DiscussionId) b on a.DiscussionId = b.DiscussionId
left join (SELECT COUNT(*) as replycnt,PostComments.PostId FROM PostComments
GROUP BY PostComments.PostId) c on b.PostId = c.PostId
where a.IsDelete = 0 and a.UserID != 33
Group by a.SuburbDiscussionID
ORDER BY TotCount
Why PostId column not detecting in my query?

How can I add a sub-query to this cursor?

I tried to add a sub query (StoCount) to the following cursor:
DECLARE trans_cur CURSOR FOR
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
(SELECT COUNT(*) FROM StorageTransportOrderItem WHERE DeliveryNumber = a.DeliveryNumber AND DeliveryItemNumber = a.DeliveryItemNumber) As StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
but when I always get the error message:
Msg 8120, Level 16, State 1, Procedure sp_CalculateTransportProgress,
Line 41 Column 'DeliveryItem.DeliveryNumber' is invalid in the select
list because it is not contained in either an aggregate function or
the GROUP BY clause. Msg 8120, Level 16, State 1, Procedure
sp_CalculateTransportProgress, Line 41 Column
'DeliveryItem.DeliveryItemNumber' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
My goal is to add this single column (StoCount) to the cursor without modifying the query too much.
Is that possible?
You could move the correlated subquery to a cross apply
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
MAX(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(*) freq FROM StorageTransportOrderItem s
WHERE s.DeliveryNumber = a.DeliveryNumber AND s.DeliveryItemNumber = a.DeliveryItemNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
Edit by xsl:
I had to modify the query a bit, so that it returned the correct results for my database:
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
SUM(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(1) freq FROM StorageTransportOrderItem s
WHERE
s.DeliveryNumber = a.DeliveryNumber
AND s.DeliveryItemNumber = a.DeliveryItemNumber
AND s.MaterialNumber = a.MaterialNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber