CASE语句中的计算

时间:2018-08-16 19:56:45

标签: sql sql-server

我试图在我的case语句中包括第4个“程序”,它将是所有加在一起的程序的组合,因为没有表ID可以标识所有(即pp.id = 2 + p.id = 3 + p.id = 4 =全部)。 CASE语句能够实现这一目标吗?合并?嵌套的SELECT?

   DECLARE @date datetime = CONVERT(date, getdate())

Select Count(Distinct fm.MEMBER_ID) As 'Count',
      Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' + Cast(DatePart(MONTH,
      dd.DATE) As VARCHAR) + '/01' As DATE) As 'Month',
      Case When p.ID = 2 Then 'Program1' When p.ID = 3 Then 'Program2'
        When p.ID = 4 Then 'Program3' End As 'Program'
    From FACT_MEMBER_MONTH_START fm
      Join DIM_COVERAGE c On fm.MEMBER_ID = c.MEMBER_ID
      Join DIM_PROGRAM p On c.PROGRAM_ID = p.ID
      Join DIM_DATE dd On fm.MONTH_ID = dd.MONTH_ID
      Join DIM_MEMBER dm On fm.MEMBER_ID = dm.ID
      Join DIM_INDIVIDUAL DI On fm.MEMBER_ID = DI.ID
      Join DIM_LIVING_SITUATION dls On fm.LIVING_SITUATION_ID = dls.ID
    Where dd.DATE Between c.EFFECTIVE_DATE And c.EXPIRATION_DATE And (dls.ID = 5
        Or dls.ID = 6) and (dd.DATE between DATEADD(MM, -18, @date) and @date)
    Group By Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' +
      Cast(DatePart(MONTH, dd.DATE) As VARCHAR) + '/01' As DATE),
      Case When p.ID = 2 Then 'FC' When p.ID = 3 Then 'PACE'
        When p.ID = 4 Then 'Part' End
 ORDER BY Month desc

结果:

Sample Results

最终目标将是“第4个程序”,仅是第3个程序的总和。这将在Logi Analytics中用于从一个查询中开发出多个图表,并可以使用这些单独的程序进行过滤。

3 个答案:

答案 0 :(得分:0)

关于UNION ALL,将您的Program1,Program2,Program3放在一起并为Program4添加新行怎么样

   DECLARE @date datetime = CONVERT(date, getdate())

Select Count(Distinct fm.MEMBER_ID) As 'Count',
      Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' + Cast(DatePart(MONTH,
      dd.DATE) As VARCHAR) + '/01' As DATE) As 'Month',
      Case When p.ID = 2 Then 'Program1' When p.ID = 3 Then 'Program2'
        When p.ID = 4 Then 'Program3' End As 'Program'
    From FACT_MEMBER_MONTH_START fm
      Join DIM_COVERAGE c On fm.MEMBER_ID = c.MEMBER_ID
      Join DIM_PROGRAM p On c.PROGRAM_ID = p.ID
      Join DIM_DATE dd On fm.MONTH_ID = dd.MONTH_ID
      Join DIM_MEMBER dm On fm.MEMBER_ID = dm.ID
      Join DIM_INDIVIDUAL DI On fm.MEMBER_ID = DI.ID
      Join DIM_LIVING_SITUATION dls On fm.LIVING_SITUATION_ID = dls.ID
    Where dd.DATE Between c.EFFECTIVE_DATE And c.EXPIRATION_DATE And (dls.ID = 5
        Or dls.ID = 6) and (dd.DATE between DATEADD(MM, -18, @date) and @date)
    Group By Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' +
      Cast(DatePart(MONTH, dd.DATE) As VARCHAR) + '/01' As DATE),
      Case When p.ID = 2 Then 'FC' When p.ID = 3 Then 'PACE'
        When p.ID = 4 Then 'Part' End

UNION ALL

Select Count(Distinct fm.MEMBER_ID) As 'Count',
      Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' + Cast(DatePart(MONTH,
      dd.DATE) As VARCHAR) + '/01' As DATE) As 'Month',

      'Program4' as 'Program'  -- they are all Program4

    From FACT_MEMBER_MONTH_START fm
      Join DIM_COVERAGE c On fm.MEMBER_ID = c.MEMBER_ID
      Join DIM_PROGRAM p On c.PROGRAM_ID = p.ID
      Join DIM_DATE dd On fm.MONTH_ID = dd.MONTH_ID
      Join DIM_MEMBER dm On fm.MEMBER_ID = dm.ID
      Join DIM_INDIVIDUAL DI On fm.MEMBER_ID = DI.ID
      Join DIM_LIVING_SITUATION dls On fm.LIVING_SITUATION_ID = dls.ID
    Where dd.DATE Between c.EFFECTIVE_DATE And c.EXPIRATION_DATE And (dls.ID = 5
        Or dls.ID = 6) and (dd.DATE between DATEADD(MM, -18, @date) and @date)
    Group By Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' +
      Cast(DatePart(MONTH, dd.DATE) As VARCHAR) + '/01' As DATE)

 ORDER BY Month desc, Program

答案 1 :(得分:0)

据我了解,您想要的是类似的东西

Select Count(Distinct fm.MEMBER_ID) As 'Count',
       Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' +
            Cast(DatePart(MONTH, dd.DATE) As VARCHAR) +
            '/01' As DATE) As 'Month',
       Case
         When p.ID = 2 Then 'Program1'
         When p.ID = 3 Then 'Program2'
         When p.ID = 4 Then 'Program3'
       End As 'Program'
  From FACT_MEMBER_MONTH_START fm
  Join DIM_COVERAGE c On fm.MEMBER_ID = c.MEMBER_ID
  Join DIM_PROGRAM p On c.PROGRAM_ID = p.ID
  Join DIM_DATE dd On fm.MONTH_ID = dd.MONTH_ID
  Join DIM_MEMBER dm On fm.MEMBER_ID = dm.ID
  Join DIM_INDIVIDUAL DI On fm.MEMBER_ID = DI.ID
  Join DIM_LIVING_SITUATION dls On fm.LIVING_SITUATION_ID = dls.ID
  Where dd.DATE Between c.EFFECTIVE_DATE And c.EXPIRATION_DATE And
        (dls.ID = 5 Or
         dls.ID = 6) and
        (dd.DATE between DATEADD(MM, -18, @date) and @date)
  Group By ROLLUP Cast(Cast(DatePart(YEAR, dd.DATE) As VARCHAR) + '/' +
                       Cast(DatePart(MONTH, dd.DATE) As VARCHAR) +
                       '/01' As DATE),
                  p.ID
  ORDER BY Month desc

答案 2 :(得分:0)

此查询可以简化一点。有一些不需要的东西,也有一些性能瓶颈可以改进。

DECLARE @date datetime = CONVERT(date, getdate()) ;  
/* 
    NOTE: getDate() returns a datetime datatype. No need to CONVERT(). 
    But, I'm guessing this input is coming in as an application input. In 
    that case, it will probably still need the CONVERT().
*/

/* s1 CTE holds the base data for the later UNIONs. */
; WITH s1 AS ( 
    SELECT Count(Distinct fm.MEMBER_ID) AS [Count]
          /* 
            There is a lot of heavy string processing for @date that can be avoided. Also, we 
            may not need the CAST. It will return the datatype of @date 
          */
        , CAST( CONVERT(varchar,DATEADD(day,-DAY(@date)+1,@date),111) AS date) AS [Month] 
        , CASE C.PROGRAM_ID
            WHEN 2 THEN 'Program1' 
            When 3 Then 'Program2'
            When 4 Then 'Program3' 
          END AS Program
    FROM FACT_MEMBER_MONTH_START fm
        INNER JOIN DIM_COVERAGE c On fm.MEMBER_ID = c.MEMBER_ID
            AND c.PROGRAM_ID IN ( 2,3,4 ) /* Do we only care about these programs? */
          /* Join DIM_PROGRAM p On c.PROGRAM_ID = p.ID */ /* Is this table needed? */
        INNER JOIN DIM_DATE dd On fm.MONTH_ID = dd.MONTH_ID
            AND dd.DATE BETWEEN DATEADD(month, -18, @date) AND @date
            AND dd.DATE BETWEEN c.EFFECTIVE_DATE AND c.EXPIRATION_DATE
        /* DIM_DATE JOIN should be able to be much simplified. */     
        INNER JOIN DIM_MEMBER dm ON fm.MEMBER_ID = dm.ID
        INNER JOIN DIM_INDIVIDUAL DI ON fm.MEMBER_ID = DI.ID
        INNER JOIN DIM_LIVING_SITUATION dls ON fm.LIVING_SITUATION_ID = dls.ID
            AND dls.ID IN ( 5, 6 )  /* Since we were filtering with these, just use in JOIN. */
    GROUP BY 
        CONVERT(varchar,DATEADD(day,-DAY(dd.DATE)+1,dd.DATE),111) /* Simplified */
        , c.PROGRAM_ID
) 
SELECT s1.[Month]
    , s1.[Count]
    , s1.Program
FROM s1    

UNION ALL

SELECT s.[Month]
    , SUM(s.[Count]) AS [Count]
    , 'Program4' AS Program
FROM s1 s    
GROUP BY s.[Month]

ORDER BY [Month],Program

我使用通用表表达式(CTE)(s1)来获取每月Program的总数,然后从CTE中获取SELECT,这应该给我一个计算所有MonthProgram的细分。然后,我再次从CTE SELECT} SUM()然后Month UNION ALL的所有程序,然后返回到第一个查询。那应该给我Month的Program4一行。

我不确定如何将其发送到您的制图系统,但是此查询也可以转换为PIVOT,以便每个Month仅包含一行。

免责声明::没有数据,我无法测试,但它应该运行得更快,并且仍返回与以前相同的数据。您可能需要调整过滤器。