Using a CASE statement...possible to Group By?

  • I apologize if this is a confusing question...

    What I'm trying to do is create a case statement that makes a field two names based on a specific condition.

    One instance is where if it's an internet source (Google, MSN, Youtube...) then I want the source to be changed to Internet. The problem I'm getting is that I have 3 rows of data that should be grouped by the source. See below:

    #CALLSSOURCE ORGSTATUS

    2INTERNETADCUSTOMER

    1INTERNETADCUSTOMER

    1INTERNETADCUSTOMER

    Here's my queryDECLARE @CALLIN INT = 3

    DECLARE @ADLEADS INT = 4

    DECLARE @INTLEADS INT = 2

    DECLARE @CUSTOMER INT = 14

    DECLARE @ADLEADFUP INT = 20

    DECLARE @DEALERDEV INT = 19

    SELECT COUNT(*) AS '#CALLS'

    ,CASE

    WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    ELSE 'DIRECT MAIL'

    END AS SOURCE

    ,CASE

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN SOURCE IN ('INTERNET') THEN (@INTLEADS - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'CUSTOMER' THEN (@CUSTOMER - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN KEY1 != 'AD' AND KEY3 = 'LEAD' THEN (@DEALERDEV - COUNT(*))

    END AS C

    ,KEY1 AS 'ORG'

    ,KEY3 AS 'STATUS'

    FROM [CAL] AS AA

    JOIN [CONTACT1] AS BB

    ON AA.ACCOUNTNO = BB.ACCOUNTNO

    WHERE USERID LIKE '%WAYNE%'

    AND AA.CREATEON = '2012-5-31'

    GROUP BY SOURCE, KEY1, KEY3

    ORDER BY ORG ASC, STATUS

    When I take out the case statement, this is my data:

    #CALLSSOURCE ORGSTATUS

    2GOOGLE ADCUSTOMER

    1INTERNET ADCUSTOMER

    1YAHOO ADCUSTOMER

    And here's my query:

    DECLARE @CALLIN INT = 3

    DECLARE @ADLEADS INT = 4

    DECLARE @INTLEADS INT = 2

    DECLARE @CUSTOMER INT = 14

    DECLARE @ADLEADFUP INT = 20

    DECLARE @DEALERDEV INT = 19

    SELECT COUNT(*) AS '#CALLS'

    --,CASE

    --WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    --ELSE 'DIRECT MAIL'

    --END AS SOURCE

    ,SOURCE

    ,CASE

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN SOURCE IN ('INTERNET') THEN (@INTLEADS - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'CUSTOMER' THEN (@CUSTOMER - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN KEY1 != 'AD' AND KEY3 = 'LEAD' THEN (@DEALERDEV - COUNT(*))

    END AS C

    ,KEY1 AS 'ORG'

    ,KEY3 AS 'STATUS'

    FROM [Goldmine].[dbo].[CAL] AS AA

    JOIN [Goldmine].[dbo].[CONTACT1] AS BB

    ON AA.ACCOUNTNO = BB.ACCOUNTNO

    WHERE USERID LIKE '%WAYNE%'

    AND AA.CREATEON = '2012-5-31'

    GROUP BY SOURCE, KEY1, KEY3

    ORDER BY ORG ASC, STATUS

    So my question is.....is there a way to group these fields together when the CASE statement makes them a different value?

  • joshd 1807 (5/31/2012)


    I apologize if this is a confusing question...

    What I'm trying to do is create a case statement that makes a field two names based on a specific condition.

    One instance is where if it's an internet source (Google, MSN, Youtube...) then I want the source to be changed to Internet. The problem I'm getting is that I have 3 rows of data that should be grouped by the source. See below:

    #CALLSSOURCE ORGSTATUS

    2INTERNETADCUSTOMER

    1INTERNETADCUSTOMER

    1INTERNETADCUSTOMER

    Here's my query

    DECLARE @CALLIN INT = 3

    DECLARE @ADLEADS INT = 4

    DECLARE @INTLEADS INT = 2

    DECLARE @CUSTOMER INT = 14

    DECLARE @ADLEADFUP INT = 20

    DECLARE @DEALERDEV INT = 19

    SELECT COUNT(*) AS '#CALLS'

    ,CASE

    WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    ELSE 'DIRECT MAIL'

    END AS SOURCE

    ,CASE

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN SOURCE IN ('INTERNET') THEN (@INTLEADS - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'CUSTOMER' THEN (@CUSTOMER - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN KEY1 != 'AD' AND KEY3 = 'LEAD' THEN (@DEALERDEV - COUNT(*))

    END AS C

    ,KEY1 AS 'ORG'

    ,KEY3 AS 'STATUS'

    FROM [CAL] AS AA

    JOIN [CONTACT1] AS BB

    ON AA.ACCOUNTNO = BB.ACCOUNTNO

    WHERE USERID LIKE '%WAYNE%'

    AND AA.CREATEON = '2012-5-31'

    GROUP BY SOURCE, KEY1, KEY3

    ORDER BY ORG ASC, STATUS

    When I take out the case statement, this is my data:

    #CALLSSOURCE ORGSTATUS

    2GOOGLE ADCUSTOMER

    1INTERNET ADCUSTOMER

    1YAHOO ADCUSTOMER

    And here's my query:

    DECLARE @CALLIN INT = 3

    DECLARE @ADLEADS INT = 4

    DECLARE @INTLEADS INT = 2

    DECLARE @CUSTOMER INT = 14

    DECLARE @ADLEADFUP INT = 20

    DECLARE @DEALERDEV INT = 19

    SELECT COUNT(*) AS '#CALLS'

    --,CASE

    --WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    --ELSE 'DIRECT MAIL'

    --END AS SOURCE

    ,SOURCE

    ,CASE

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN SOURCE IN ('INTERNET') THEN (@INTLEADS - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'CUSTOMER' THEN (@CUSTOMER - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN KEY1 != 'AD' AND KEY3 = 'LEAD' THEN (@DEALERDEV - COUNT(*))

    END AS C

    ,KEY1 AS 'ORG'

    ,KEY3 AS 'STATUS'

    FROM [Goldmine].[dbo].[CAL] AS AA

    JOIN [Goldmine].[dbo].[CONTACT1] AS BB

    ON AA.ACCOUNTNO = BB.ACCOUNTNO

    WHERE USERID LIKE '%WAYNE%'

    AND AA.CREATEON = '2012-5-31'

    GROUP BY SOURCE, KEY1, KEY3

    ORDER BY ORG ASC, STATUS

    So my question is.....is there a way to group these fields together when the CASE statement makes them a different value?

    Here:

    DECLARE @CALLIN INT = 3

    DECLARE @ADLEADS INT = 4

    DECLARE @INTLEADS INT = 2

    DECLARE @CUSTOMER INT = 14

    DECLARE @ADLEADFUP INT = 20

    DECLARE @DEALERDEV INT = 19

    SELECT COUNT(*) AS '#CALLS'

    ,CASE

    WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    ELSE 'DIRECT MAIL'

    END AS SOURCE

    ,CASE

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN SOURCE IN ('INTERNET') THEN (@INTLEADS - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'CUSTOMER' THEN (@CUSTOMER - COUNT(*))

    WHEN KEY1 = 'AD' AND KEY3 = 'LEAD' THEN (@ADLEADS - COUNT(*))

    WHEN KEY1 != 'AD' AND KEY3 = 'LEAD' THEN (@DEALERDEV - COUNT(*))

    END AS C

    ,KEY1 AS 'ORG'

    ,KEY3 AS 'STATUS'

    FROM [CAL] AS AA

    JOIN [CONTACT1] AS BB

    ON AA.ACCOUNTNO = BB.ACCOUNTNO

    WHERE USERID LIKE '%WAYNE%'

    AND AA.CREATEON = '2012-5-31'

    GROUP BY

    ,CASE

    WHEN SOURCE IN ('INTERNET', 'YOUTUBE', 'GOOGLE', 'BING', 'MSN', 'YAHOO') THEN 'INTERNET'

    ELSE 'DIRECT MAIL'

    END,

    KEY1,

    KEY3

    ORDER BY ORG ASC, STATUS

  • Nevermind...my solution was wrong 🙁

  • I wasn't aware you could put the case statements into the GROUP BY clause...that's interesting! I need to be more daring in writing code 🙂

    Unfortunately the query doesn't work because it's looking for SOURCE in the GROUP BY clause. I enter it in and it doesn't give me any results.

    I enter the case as follows:

    CASE

    ...

    END AS SOURCE

    And it throws an error stating there's an error 'Incorrect syntax near the keyword 'AS'.'

  • joshd 1807 (5/31/2012)


    I wasn't aware you could put the case statements into the GROUP BY clause...that's interesting! I need to be more daring in writing code 🙂

    Unfortunately the query doesn't work because it's looking for SOURCE in the GROUP BY clause. I enter it in and it doesn't give me any results.

    I enter the case as follows:

    CASE

    ...

    END AS SOURCE

    And it throws an error stating there's an error 'Incorrect syntax near the keyword 'AS'.'

    Which table is the column SOURCE located? Add the table alias to the column name in the case statement in the GROUP BY clause. Do not alias the CASE in the GROUP BY.

    FYI, it is a good practice to use the table alias on all your columns, especially in multi-table queries.

  • joshd 1807 (5/31/2012)


    I wasn't aware you could put the case statements into the GROUP BY clause...that's interesting! I need to be more daring in writing code 🙂

    Unfortunately the query doesn't work because it's looking for SOURCE in the GROUP BY clause. I enter it in and it doesn't give me any results.

    I enter the case as follows:

    CASE

    ...

    END AS SOURCE

    And it throws an error stating there's an error 'Incorrect syntax near the keyword 'AS'.'

    Get rid of the "AS SOURCE" - you can't use a column alias in the GROUP BY clause.

    So for example:

    SELECT

    CASE WHEN Something = 'Some value' then 1

    ELSE 0 END AS MY_ALIAS

    FROM

    SOME_TABLE

    GROUP BY

    CASE WHEN Something = 'Some value' then 1

    ELSE 0 END /* <-- No alias! */

  • If you want to display the results of the CASE expression and use it in a GROUP BY, you can use a CROSS APPLY to define and alias the CASE Statement.

    SELECT cs.Source

    FROM YourTable

    CROSS APPLY (

    SELECT CASE ... END AS Source

    ) AS cs

    GROUP BY cs.Source

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Thank you so much

  • For What it is worth, If I have to repeat the CASE logic in the WHERE or GROUP clauses, I prefer to wrap the original query as a CTE and then select from the CTE using the converted values. I find this cleaner to read and it means that if the CASE logic changes, only have to change it in one place. As far as I am aware the query plans that will be generated will be identical.

    Even better, if you have a 1:many conversion, put an @inMemory or #temp table in the top of the script and populate the conversion data there, This helps to keep the main query clean, makes the maintenance of the script simpler as you can only have to configure the variables at the top of the script and should the relationships ever become more complicated (e.g. based on two distinct attributes) then it is simpler to modify the table than to re-write the entire CASE statement.

    The other thing you need to be wary of is that the CASE statement will be triggered by the first matching rule, so the order of the WHENs can be important and have to go from most specific to least specific with the ELSE clause being a catch-all

    Normally when you see this sort of CASE there is a missing hierarchical or attribute relationship in the domain and if possible you should be investing the development time in capturing the data within the domain model. What happens if the source comes in via Twitter, or a smart TV,or a microwave link?

Viewing 9 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic. Login to reply