I was trying to do this:
SELECT COUNT(*),
(
SELECT COUNT(*) FROM attend
WHERE (DATEPART(WEEKDAY,start_date) = 2 OR DATEPART(WEEKDAY,start_date) = 6)
AND empl_no = 12345
)
FROM attend as a
WHERE empl_no = 12345
But this seems a little ugly. Is there a better way to do this?
You could use a CTE:
WITH T1 AS (
SELECT DATEPART(WEEKDAY,start_date) AS weekday
FROM attend
WHERE empl_no = 12345
)
SELECT
(SELECT COUNT(*) FROM T1) AS total,
(SELECT COUNT(*) FROM T1 WHERE weekday = 2 OR weekday = 6) AS subset
Use:
SELECT COUNT(*) AS total,
SUM(CASE
WHEN DATEPART(WEEKDAY, t.start_date) IN (2,6) THEN 1
ELSE 0
END) AS weekday
FROM ATTEND t
WHERE t.empl_no = 12345
CUBE
and ROLLUP
are very useful for dealing with final and intermediate aggregates all in one shot. For this type of question CUBE would be a good fit if the final and intermediate totals were needed so this and similar questions could be answered without additional queries from the source table. I've found CUBE very useful for avoiding round trips to the DB. However, in the case where the exact requirements are known ahead of time a single focused select (nicely demonstrated by @nate c) makes the most sense.
DECLARE @T1 TABLE (total int, weekday int)
INSERT INTO @T1
SELECT COUNT(1), DATEPART(WEEKDAY,start_date)
FROM attend
WHERE empl_no = 12345
GROUP BY DATEPART(WEEKDAY,start_date) WITH CUBE
SELECT
(SELECT Total FROM @T1 WHERE weekday is NULL) AS total,
(SELECT SUM(weekday) FROM @T1 WHERE weekday = 2 or weekday = 6) AS subset
-- continue using @T1 or a table variable was seriously overkill