My code is as follows:
SELECT DISTINCT
lc.locationName,
(SELECT SUM(c.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_ONE%'
AND s.Date >= GETDATE()) AS TYPE_ONE_COUNT,
(SELECT SUM(c.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_TWO%'
AND s.Date >= GETDATE()) AS TYPE_TWO_COUNT,
(SELECT SUM(c.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_THREE%'
AND s.Date >= GETDATE()) AS TYPE_THREE_COUNT
FROM
Schedule AS sc WITH (NOLOCK) --/*This table has timeslotscount, serviceid*/
LEFT JOIN
ServiceList AS sv ON sv.ServiceId = sc.ServiceId --/*This table has locationid, serviceid(type1/type2/type3 depending on location[all locations has type1/2/3])*/
LEFT JOIN
Location AS lc ON sv.LocationId = lc.LocationId --/*This table has locationid, locationname*/
I should explain the SUM(), there are differing dates on schedule such as
serviceId | dd/mm/yyyy hh:mm:ss | count for this day
I want to get all the "count" of "serviceId" beyond today hence the 'date >= GETDATE()'
Basically I want the table to look like so:
LOCATION | TYPE_ONE_COUNT | TYPE_TWO_COUNT | TYPE_THREE_COUNT
I am able to get the values but I get them like so:
LocationOne | 12 | 0 | 0
LocationOne | 0 | 12 | 0
LocationOne | 0 | 0 | 34
LocationTwo | 1 | 0 | 0
LocationTwo | 0 | 42 | 0
LocationTwo | 0 | 0 | 9
Whereas I want to display as
LocationOne | 12 | 12 | 34
LocationTwo | 1 | 42 | 9
Any and all help is appreciated. Where I'm wrong, syntax/performance improvement, references, anything.
CodePudding user response:
You can do it with conditional aggregation:
SELECT lc.locationName,
SUM(CASE WHEN sv.ServiceName LIKE '%TYPE_ONE%' THEN sc.TimeSlotsCount ELSE 0 END) AS TYPE_ONE_COUNT,
SUM(CASE WHEN sv.ServiceName LIKE '%TYPE_TWO%' THEN sc.TimeSlotsCount ELSE 0 END) AS TYPE_TWO_COUNT,
SUM(CASE WHEN sv.ServiceName LIKE '%TYPE_THREE%' THEN sc.TimeSlotsCount ELSE 0 END) AS TYPE_THREE_COUNT
FROM Location AS lc
LEFT JOIN ServiceList AS sv ON sv.LocationId = lc.LocationId
LEFT JOIN Schedule AS sc ON sv.ServiceId = sc.ServiceId AND sc.Date >= GETDATE()
GROUP BY lc.LocationId, lc.locationName;
CodePudding user response:
A few ways. One is to simply perform one last operation:
Note also: I adjusted the original SQL, since c.TimeSlotsCount does not exist. You have no c table/alias. I added TimeSlotsCount to the Schedule table. Adjust that as needed, based on the actual source of TimeSlotsCount.
WITH cte AS (
Your above SQL from the question, without semicolon
)
SELECT locationName
, SUM(TYPE_ONE_COUNT) AS TYPE_ONE_COUNT
, SUM(TYPE_TWO_COUNT) AS TYPE_TWO_COUNT
, SUM(TYPE_THREE_COUNT) AS TYPE_THREE_COUNT
FROM cte
GROUP BY locationName
;
We could have also done a slightly different SUM in the original SQL, without the DISTINCT and with the GROUP BY, avoiding the extra CTE term.
But logically, these are the same.
Final SQL, using your SQL directly:
WITH cte AS (
SELECT DISTINCT
lc.locationName,
(SELECT SUM(s.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_ONE%'
AND s.Date >= GETDATE()) AS TYPE_ONE_COUNT,
(SELECT SUM(s.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_TWO%'
AND s.Date >= GETDATE()) AS TYPE_TWO_COUNT,
(SELECT SUM(s.TimeSlotsCount) FROM Schedule s
WHERE s.ServiceId = sv.ServiceId
AND sv.LocationId = lc.LocationId
AND sv.ServiceName LIKE '%TYPE_THREE%'
AND s.Date >= GETDATE()) AS TYPE_THREE_COUNT
FROM
Schedule AS sc WITH (NOLOCK) --/*This table has timeslotscount, serviceid*/
LEFT JOIN
ServiceList AS sv ON sv.ServiceId = sc.ServiceId --/*This table has locationid, serviceid(type1/type2/type3 depending on location[all locations has type1/2/3])*/
LEFT JOIN
Location AS lc ON sv.LocationId = lc.LocationId --/*This table has locationid, locationname*/
)
SELECT locationName
, SUM(TYPE_ONE_COUNT) AS TYPE_ONE_COUNT
, SUM(TYPE_TWO_COUNT) AS TYPE_TWO_COUNT
, SUM(TYPE_THREE_COUNT) AS TYPE_THREE_COUNT
FROM cte
GROUP BY locationName
;
