【问题标题】:Show LastDateOfMonth even where there is no value [duplicate]即使没有价值也显示 LastDateOfMonth [重复]
【发布时间】:2015-02-02 13:42:14
【问题描述】:

这是我正在做的事情:

  WITH cte AS (
  SELECT * FROM TimeDim 
  )
SELECT t.TimeDimPK, c.ID 
FROM CTE AS t
LEFT OUTER JOIN TABLE c ON c.TimeDimFK = t.TimeDimPK
ORDER BY t.TimeDimPK
WHERE c.ID = 1

结果,缺少日期如下图:

TimeDimPK   ID
20120930    1
20121231    1
20130131    1

我想得到什么

TimeDimPK   ID
20120930    1
20121031    NULL
20121130    NULL
20121231    1
20130131    1

【问题讨论】:

    标签: sql-server left-join common-table-expression


    【解决方案1】:

    看起来您的WHERE 子句正在删除其他日期。试试这个:

    WITH    cte
              AS ( SELECT   TimedimPK
                   FROM     TimeDim
                 )
        SELECT  t.TimeDimPK ,
                c.ID
        FROM    cte t
                LEFT OUTER JOIN TABLEname c ON c.TimeDimFK = t.TimeDimPK
        WHERE   c.ID = 1
                OR c.ID IS NULL
        ORDER BY t.TimeDimPK
    

    【讨论】:

    • 这对我不起作用:(我需要查询来生成缺少的日期,同时在 ID 上使用 where。
    • 您需要提供更多描述性反馈,然后“这对我不起作用”。运行查询时,缺少什么?
    • 我需要查询来生成缺少的日期,同时对特定 ID 使用 where 条件。
    【解决方案2】:

    您可以尝试使用“数字/日期生成器”,此查询将填写所有缺失的日期,然后选择该月的最后一天。我不确定你所有的数据细节,所以我目前给你两个建议:

    1 - 简洁建议:

    DECLARE @minDate DATETIME, @maxDate DATETIME;
    
    SELECT @minDate = MIN(TimeDimPK), @maxDate = MAX(TimeDimPK) FROM TimeDim;
    
    WITH DateGenerator AS
    (
        --Create a list with a lot of dates from @minDate
        SELECT TimeDimPK = CONVERT(DATE, DATEADD(dd, ROW_NUMBER() OVER (ORDER BY OBJECT_ID), @minDate)) FROM sys.objects
    )
    --List all days, including missing days
    SELECT TimeDimPK
    , c.ID
    FROM DateGenerator n
    LEFT JOIN AnotherTable c ON c.TimeDimFK = n.TimeDimPK
    WHERE 
    --Stop the number generator at the last day of the last month from the cte table
    n.TimeDimPK <=  CONVERT(DATE, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0, @maxDate )+1,0)))
    --This will get the last day of every month
    AND TimeDimPK = CONVERT(DATE, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,TimeDimPK)+1,0)))
    



    2 - 如果您想将其用于一些调整,请对您的 cte 子句提出建议:

    WITH NumberGenerator AS
    (
        --Create a number list 1,2,3,4,5,6,7,8,++
        SELECT Number = ROW_NUMBER() OVER (ORDER BY OBJECT_ID) FROM sys.objects
    ), cte AS (
        --Your cte query with a date number based on the days between the firts and current days
        SELECT 
        TimeDimPK = CONVERT(DATETIME, TimeDimPK)
        --Get the number of days to add from the first day in your table
        , DateNumber = DATEDIFF(dd,  MIN(TimeDimPK) OVER (), TimeDimPK)
        FROM #TimeDim 
    ), TableWithMissingDates AS
    (
        --Fill missing days
        SELECT TimeDimPK = CONVERT(DATE, DATEADD(dd, n.Number - 1, MIN(t.TimeDimPK) OVER ()))
        , c.ID
        FROM NumberGenerator n
        LEFT JOIN cte t ON t.DateNumber = n.Number 
        LEFT JOIN #Test2 c ON c.TimeDimFK = t.TimeDimPK
        --Stop the number generator at the last day of the last month from the cte table
        WHERE CONVERT(DATE, DATEADD(dd, n.Number - 1, (SELECT MIN(TimeDimPK) FROM cte))) <  CONVERT(DATE, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0, (SELECT MAX(TimeDimPK) FROM cte) )+1,0)))
    )
    SELECT * FROM TableWithMissingDates
    WHERE 
    --This will get the last day of every month
    TimeDimPK = CONVERT(DATE, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,TimeDimPK)+1,0)))
    



    两个查询都将返回同一个表:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      • 1970-01-01
      • 2012-01-17
      • 2017-09-06
      相关资源
      最近更新 更多