Invalid column name error while using left join - sql

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?

Related

GROUP BY clause SQL invalid aggregate function

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'

Select an ID where there is only one row and that row is a specific value

I have this query. There's a lot of joins because I am checking if an ID is linked to any of those tables.
Currently, this query shows me any ID's that are not linked to any of those tables. I would like to add to it so that it also shows any IDs that are linked to the d table, but only if there is only 1 row in the D table and the type in the D field is 'member'.
SELECT
c.ID,
c.location,
c.pb,
c.name,
c.surname
FROM c
LEFT JOIN l on c.rowno = l.rowno
LEFT JOIN d on c.rowno = d.rowno
LEFT JOIN t on c.rowno = t.rowno
LEFT JOIN cj ON (c.rowno = cj.rowno OR c.rowno = cj.rowno2)
LEFT JOIN dj ON c.rowno = d.rowno
LEFT JOIN lg ON c.rowno = lg.rowno
LEFT JOIN tj ON c.rowno = tj.rowno
WHERE
c.status != 'closed'
AND l.rowno IS NULL
AND d.rowno IS NULL
AND t.rowno IS NULL
AND cj.rowno IS NULL
AND dj.rowno IS NULL
AND lg.rowno IS NULL
AND tj.rowno IS NULL
My first thought is to just add
WHERE D.type = 'member'
But that gives me all IDs that have a row with D.type = member (they could have 10 rows with all different types, but as long as 1 of those has type = member it shows up). I want to see ID's that ONLY have d.type = member
I'm sorry if I'm wording this badly, I'm having trouble getting this straight in my head. Any help is appreciated!
I would use exists for all conditions except the one on the D table:
SELECT c.*
FROM c JOIN
(SELECT d.rownum, COUNT(*) as cnt,
SUM(CASE WHEN d.type = 'Member' THEN 1 ELSE 0 END) as num_members
FROM t
GROUP BY d.rownum
) d
ON c.rownum = d.rownum
WHERE c.status <> 'closed' AND
NOT EXISTS (SELECT 1 FROM t WHERE c.rowno = t.rowno) AND
NOT EXISTS (SELECT 1 FROM l WHERE c.rowno = l.rowno) AND
. . .
I find NOT EXISTS is easier to follow logically. I don't think there is a big performance difference between the two methods in SQL Server.

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.

SQl Error : Each GROUP BY expression must contain at least one column that is not an outer reference [duplicate]

This question already has answers here:
Each GROUP BY expression must contain at least one column that is not an outer reference
(8 answers)
Closed 6 years ago.
I get this error
Each GROUP BY expression must contain at least one column that is not an outer reference
while running this query:
SELECT TOP 1
SUM(mla.total_current_attribute_value)
FROM
partstrack_machine_location_attributes mla (NOLOCK)
INNER JOIN
#tmpInstallParts_Temp installpartdetails ON mla.machine_sequence_id = installpartdetails.InstallKitToMachineSequenceId
AND (CASE WHEN mla.machine_side_id IS NULL THEN 1
WHEN mla.machine_side_id = installpartdetails.InstallKitToMachineSideId THEN 1 END
) = 1
INNER JOIN
partstrack_mes_attribute_mapping mam (NOLOCK) ON mla.mes_attribute = mam.mes_attribute_name
INNER JOIN
partstrack_attribute_type at (NOLOCK) ON mam.pt_attribute_id = at.pt_attribute_id
INNER JOIN
partstrack_ipp_mes_attributes ima(NOLOCK) ON at.pt_attribute_id = ima.pt_attribute_id
WHERE
mla.active_ind = 'Y' AND
ima.ipp_ID IN (SELECT ipp.ipp_id
FROM partstrack_individual_physical_part ipp
INNER JOIN #tmpInstallParts_Temp tmp ON (ipp.ipp_id = tmp.InstallingPartIPPId OR
(CASE WHEN tmp.InstallingPartIPKId = '-1' THEN 1 END) = 1
)
GROUP BY
ima.ipp_id
Can someone help me?
This is the text of the query from the first revision of the question.
In later revisions you removed the last closing bracket ) and the query became syntactically incorrect. You'd better check and fix the text of the question and format the text of the query, so it is readable.
SELECT TOP 1
SUM(mla.total_current_attribute_value)
FROM
partstrack_machine_location_attributes mla (NOLOCK)
INNER JOIN #tmpInstallParts_Temp installpartdetails
ON mla.machine_sequence_id = installpartdetails.InstallKitToMachineSequenceId
AND (CASE WHEN mla.machine_side_id IS NULL THEN 1
WHEN mla.machine_side_id = installpartdetails.InstallKitToMachineSideId THEN 1 END) = 1
INNER JOIN partstrack_mes_attribute_mapping mam (NOLOCK) ON mla.mes_attribute = mam.mes_attribute_name
INNER JOIN partstrack_attribute_type at (NOLOCK) ON mam.pt_attribute_id = at.pt_attribute_id
INNER JOIN partstrack_ipp_mes_attributes ima(NOLOCK) ON at.pt_attribute_id = ima.pt_attribute_id
WHERE
mla.active_ind = 'Y'
AND ima.ipp_ID IN
(
Select
ipp.ipp_id
FROM
partstrack_individual_physical_part ipp
INNER JOIN #tmpInstallParts_Temp tmp
ON (ipp.ipp_id = tmp.InstallingPartIPPId
OR (CASE WHEN tmp.InstallingPartIPKId = '-1' THEN 1 END) = 1)
GROUP BY
ima.ipp_id
)
With this formatting it is clear now that there is a subquery with GROUP BY.
Most likely it is just a typo: you meant to write GROUP BY ipp.ipp_id instead of GROUP BY ima.ipp_id.
If you really wanted to have the GROUP BY not in a subquery, but in the main SELECT, then you misplaced the closing bracket ) and the query should look like this:
SELECT TOP 1
SUM(mla.total_current_attribute_value)
FROM
partstrack_machine_location_attributes mla (NOLOCK)
INNER JOIN #tmpInstallParts_Temp installpartdetails
ON mla.machine_sequence_id = installpartdetails.InstallKitToMachineSequenceId
AND (CASE WHEN mla.machine_side_id IS NULL THEN 1
WHEN mla.machine_side_id = installpartdetails.InstallKitToMachineSideId THEN 1 END) = 1
INNER JOIN partstrack_mes_attribute_mapping mam (NOLOCK) ON mla.mes_attribute = mam.mes_attribute_name
INNER JOIN partstrack_attribute_type at (NOLOCK) ON mam.pt_attribute_id = at.pt_attribute_id
INNER JOIN partstrack_ipp_mes_attributes ima(NOLOCK) ON at.pt_attribute_id = ima.pt_attribute_id
WHERE
mla.active_ind = 'Y'
AND ima.ipp_ID IN
(
Select
ipp.ipp_id
FROM
partstrack_individual_physical_part ipp
INNER JOIN #tmpInstallParts_Temp tmp
ON (ipp.ipp_id = tmp.InstallingPartIPPId
OR (CASE WHEN tmp.InstallingPartIPKId = '-1' THEN 1 END) = 1)
)
GROUP BY
ima.ipp_id
In any case, proper formatting of the source code can really help.
Group By ima.ipp_id
should be applicable to outer query. Because of incorrect placement of '(' it was applying to inner query.
Now after correcting the query,it's working fine without any issues.
Final Query is :
SELECT TOP 1
SUM(mla.total_current_attribute_value)
FROM
partstrack_machine_location_attributes mla (NOLOCK)
INNER JOIN #tmpInstallParts_Temp installpartdetails
ON mla.machine_sequence_id = installpartdetails.InstallKitToMachineSequenceId
AND (CASE WHEN mla.machine_side_id IS NULL THEN 1
WHEN mla.machine_side_id = installpartdetails.InstallKitToMachineSideId THEN 1 END ) = 1
INNER JOIN partstrack_mes_attribute_mapping mam (NOLOCK) ON mla.mes_attribute = mam.mes_attribute_name
INNER JOIN partstrack_attribute_type at (NOLOCK) ON mam.pt_attribute_id = at.pt_attribute_id
INNER JOIN partstrack_ipp_mes_attributes ima(NOLOCK) ON at.pt_attribute_id = ima.pt_attribute_id
WHERE
mla.active_ind = 'Y'
AND ima.ipp_ID IN
(
Select
ipp.ipp_id
FROM
partstrack_individual_physical_part ipp
INNER JOIN #tmpInstallParts_Temp tmp
ON (ipp.ipp_id = tmp.InstallingPartIPPId
OR (CASE WHEN tmp.InstallingPartIPKId = '-1' THEN 1 END ) =1)
)
GROUP BY ima.ipp_id
Thank you all.

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