Search code examples
ssasmdxolapcubeolap-cube

MDX query to pivot table based on condition


I'm trying to write MDX query for pivot table.

Similar query in RDBMS is like this:

SELECT  stats_Date
        ,ISNULL(SUM(clicks), 0) AS clicks
        ,ISNULL(SUM(CASE WHEN ad_type IN (1,3) THEN clicks END), 0) AS keyword_clicks
        ,ISNULL(SUM(CASE WHEN ad_type IN (2,3) THEN clicks END), 0) AS direct_clicks
FROM    STATS_TABLE (NOLOCK)
WHERE   stats_Date BETWEEN '2015-06-01' AND '2015-06-30'
GROUP BY stats_Date

I've two dimensions [DIM TIME] & [DIM AD TYPE]

I've tried below MDX query for this:

WITH    
    MEMBER [Measures].[Clicks Keyword] AS     
        IIF
        (
          [DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
         ,[Measures].[clicks]
         ,0
        )
SELECT  {
          [Measures].[Clicks]
         ,[Measures].[Clicks Keyword]
        } ON COLUMNS
        ,{ 
          [DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]
        }  ON ROWS
FROM    [CM_STATS_CUBE]
WHERE   ([DIM TIME].[Month].&[201506]:[DIM TIME].[Month].&[201506]})

Sample output of this MDX query looks like this:

                       Clicks       Clicks Keyword
20150501    Invalid    (null)       0             
20150501    unknown    200          0
20150501    Keyword    500          0
20150501    Ads        300          300
20150502    Invalid    (null)       0
20150502    unknown    400          0
20150502    Keyword    600          0
20150502    Ads        500          500

but I want to only group by stats_date and the expected output is:

            Clicks      Clicks Keyword
20150501    1000        300
20150502    1500        500    

Similar example for testing in [Adventure Works] cube database:

WITH 
  MEMBER [Measures].[Internet Sales Amount US] AS  
    IIF( [Customer].[Customer Geography].CurrentMember IS [Customer].[Customer Geography].[Country].&[United States]
         ,[Measures].[Internet Sales Amount]
         ,NULL
       )
SELECT {
         [Measures].[Internet Sales Amount]
        ,[Measures].[Internet Sales Amount US]
       } ON 0
       ,NON EMPTY{[Date].[Calendar].[Date]} ON 1
FROM [Adventure Works]
WHERE   {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}

Solution

  • You don't need to bother with the cross-join [DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]

    WITH 
      MEMBER [Measures].[Clicks Keyword] AS 
        IIF
        (
          [DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
         ,[Measures].[clicks]
         ,0
        ) 
    SELECT 
      {
        [Measures].[Clicks]
       ,[Measures].[Clicks Keyword]
      } ON COLUMNS
     ,{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
    FROM [CM_STATS_CUBE]
    WHERE 
      [DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
    

    Also I would suggest using null rather than 0 in your IIF function - this should tidy up the result and speed things up:

    WITH 
      MEMBER [Measures].[Clicks Keyword] AS 
        IIF
        (
          [DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
         ,[Measures].[clicks]
         ,null   //<<<<<<<<<<<<<<<<< better to use null rather than 0
        ) 
    SELECT 
      {
        [Measures].[Clicks]
       ,[Measures].[Clicks Keyword]
      } ON COLUMNS
     , NON EMPTY  //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
      {[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
    FROM [CM_STATS_CUBE]
    WHERE 
      [DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
    

    Edit

    I'd not read your script in enough detail - apologies. You can just just aggregate a set of two tuples:

    WITH 
      MEMBER [Measures].[Clicks Keyword] AS 
        Sum
        (
         {
          ([DIM AD TYPE].[Ad Type].&[1],[Measures].[clicks])
         ,([DIM AD TYPE].[Ad Type].&[3],[Measures].[clicks])
         }
        ) 
    SELECT 
      {
        [Measures].[Clicks]
       ,[Measures].[Clicks Keyword]
      } ON COLUMNS
     , NON EMPTY  //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
      {[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
    FROM [CM_STATS_CUBE]
    WHERE 
      [DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
    

    The AdvWrks example you posted would just be a single tuple:

    WITH 
      MEMBER [Measures].[Internet Sales Amount US] AS  
          (
            [Customer].[Customer Geography].[Country].&[United States]
           ,[Measures].[Internet Sales Amount]
          )
    SELECT {
             [Measures].[Internet Sales Amount]
            ,[Measures].[Internet Sales Amount US]
           } ON 0
           ,NON EMPTY{[Date].[Calendar].[Date]} ON 1
    FROM [Adventure Works]
    WHERE   {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}
    

    If you wanted to add in Canada then there seem to be three viable alternatives:

    1.

    WITH 
      MEMBER [Measures].[Internet Sales Amount US & Canada] AS  
          (
            [Customer].[Customer Geography].[Country].&[United States]
           ,[Measures].[Internet Sales Amount]
          )
        +
          (
            [Customer].[Customer Geography].[Country].&[Canada]
           ,[Measures].[Internet Sales Amount]
          )
    

    2.

     WITH 
      MEMBER [Measures].[Internet Sales Amount US & Canada] AS 
        Aggregate
        (
          {
            [Customer].[Customer Geography].[Country].&[United States]
           ,[Customer].[Customer Geography].[Country].&[Canada]
          }
         ,[Measures].[Internet Sales Amount]
        ) 
    

    3. (Switch to Sum)

    WITH 
       MEMBER [Measures].[Internet Sales Amount US & Canada] AS 
        Sum
        (
          {
            (
              [Customer].[Customer Geography].[Country].&[Canada]
             ,[Measures].[Internet Sales Amount]
            )
           ,(
              [Customer].[Customer Geography].[Country].&[United States]
             ,[Measures].[Internet Sales Amount]
            )
          }
        )