7

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)

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 = 1

2 Answers 2

7

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

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=1

Edit:

An aggregate without GROUP BY will always return a result (see SO here). I forgot that.

I've updated my SQL

0
2
DECLARE @Inbox  bigint
DECLARE @Unread bigint
DECLARE @Flagged bigint
/*
MORE DECLARE STATEMENTS GO HERE
*/

SET @Inbox   = SELECT Count(*) FROM MESSAGE WHERE [to] = [uid] 
SET @Unread  = SELECT Count(*) FROM MESSAGE WHERE [to] = [uid] and isread = 0
SET @Flagged = SELECT Count(*) FROM MESSAGE WHERE [to] = [uid] and isFlagged = 1

/*
MORE SELECT STATEMENTS GO HERE
*/

SELECT
@Inbox   as Inbox,
@Unread  as Unread,
@Flagged as Flagged

/*
MORE @Variables GO HERE
*/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.