patternMinor
Most efficient way to return multiple aggregates in a single stored proc?
Viewed 0 times
storedaggregatesreturnefficientwaysingleprocmultiplemost
Problem
What is the best or most efficient way to get multiple aggregate result values?
Basically I have an email app and wanted to get all the numbers of messages for each type of folder (inbox, sent, archived, flagged... ) as defined below.
Here is a sample of things I am trying to do in one stored proc call. (where [uid] is the userID)
Basically I have an email app and wanted to get all the numbers of messages for each type of folder (inbox, sent, archived, flagged... ) as defined below.
Here is a sample of things I am trying to do in one stored proc call. (where [uid] is the userID)
SELECT * FROM Message
Inbox WHERE [to] = [uid]
Unread WHERE [to] = [uid] and isread = 0
Flagged WHERE [to] = [uid] and isFlagged = 1
Drafts WHERE [to] = [uid] and isDraft = 1
Sent Messages WHERE [from] = [uid]
Archived Messages WHERE [to] = [uid] and isArchived = 1Solution
COUNT..CASE is the usual way. For "Sent" though it's bit trickier because it's a different uid filter which requires 2 queries on the Message table
I've used this construct to allow for zero row for to/from. It avoids an OR and adding a uid filter to each CASE.
Each derived table (can write as a CTE) will return only one row and I've used a MAX on uid to avoid GROUP BY too in case anyone wonders
Edit:
An aggregate without GROUP BY will always return a result (see SO here). I forgot that.
I've updated my SQL
I've used this construct to allow for zero row for to/from. It avoids an OR and adding a uid filter to each CASE.
Each derived table (can write as a CTE) will return only one row and I've used a MAX on uid to avoid GROUP BY too in case anyone wonders
SELECT
ISNULL(M.Inbox, 0) AS Inbox,
ISNULL(M.Unread, 0) AS Unread,
ISNULL(M.Flagged, 0) AS Flagged,
ISNULL(M.Drafts, 0) AS Drafts,
ISNULL(S.Sent, 0) AS Sent,
ISNULL(M.Archived, 0) AS Archived
FROM
(
SELECT
COUNT(*) AS InBox,
COUNT(CASE WHEN isread = 0 THEN 1 ELSE NULL END) Unread,
COUNT(CASE WHEN isFlagged = 1 THEN 1 ELSE NULL END) Flagged,
COUNT(CASE WHEN isDraft = 1 THEN 1 ELSE NULL END) Drafts,
S.Sent,
COUNT(CASE WHEN isArchived = 0 THEN 1 ELSE NULL END) Archived
FROM
Message
WHERE
[to] = [uid]
) M
FULL OUTER JOIN
(
SELECT COUNT(*) AS Sent
FROM Message
WHERE [from] = [uid]
) S ON 1=1Edit:
An aggregate without GROUP BY will always return a result (see SO here). I forgot that.
I've updated my SQL
Code Snippets
SELECT
ISNULL(M.Inbox, 0) AS Inbox,
ISNULL(M.Unread, 0) AS Unread,
ISNULL(M.Flagged, 0) AS Flagged,
ISNULL(M.Drafts, 0) AS Drafts,
ISNULL(S.Sent, 0) AS Sent,
ISNULL(M.Archived, 0) AS Archived
FROM
(
SELECT
COUNT(*) AS InBox,
COUNT(CASE WHEN isread = 0 THEN 1 ELSE NULL END) Unread,
COUNT(CASE WHEN isFlagged = 1 THEN 1 ELSE NULL END) Flagged,
COUNT(CASE WHEN isDraft = 1 THEN 1 ELSE NULL END) Drafts,
S.Sent,
COUNT(CASE WHEN isArchived = 0 THEN 1 ELSE NULL END) Archived
FROM
Message
WHERE
[to] = [uid]
) M
FULL OUTER JOIN
(
SELECT COUNT(*) AS Sent
FROM Message
WHERE [from] = [uid]
) S ON 1=1Context
StackExchange Database Administrators Q#2565, answer score: 7
Revisions (0)
No revisions yet.