【问题标题】:If Value is present in two consecutive months , display only one month in sql如果 Value 连续两个月出现,则在 sql 中只显示一个月
【发布时间】:2018-01-19 04:23:46
【问题描述】:

我想连续几个月检查 ID,如果连续两个月存在相同的 ID,则仅考虑第 1 个月的 ID。 如果 ID 不是连续月份,则显示按开始日期月份分组的不同 ID。(我们只考虑开始日期) 例如,ID 1 存在于 1 月和 2 月的开始日期月份,那么此 ID 的不同计数将在 1 月为 1,但 ID 2 和 3 是什么
出现在 1 月和 3 月以及 2 月和 5 月 Resp,现在我想在 1 月和 3 月看到这个不同的 ID 计数。 当前数据

表1:

ID    StartDate      EndDate
1     2017-01-12     2017-01-28
1     2017-01-19     2017-01-28
1     2017-01-29     2017-02-11
1     2017-02-01     2017-02-11
1     2017-02-19     2017-02-24
2     2017-01-12     2017-01-28
2     2017-01-19     2017-01-28
2     2017-03-09     2017-03-20
3     2017-02-12     2017-02-28
3     2017-02-19     2017-02-28
3     2017-05-05     2017-05-29
3     2017-05-09     2017-05-29

我尝试了以下逻辑 bt 我知道我在这里遗漏了一些东西。

select t.* from Table1 t
join Table1 t t1
on t1.ID=t.ID 
and datepart(mm,t.StartDate)<> datepart(mm,t1.StartDate)+1

预期结果:

DistinctCount     StartDateMonth(In Numbers)
   1                 1(Jan)
   2                 1(Jan)
   2                 3(March)
   3                 2(Feb)
   3                 5(May)

感谢任何帮助!

【问题讨论】:

    标签: sql-server tsql sql-server-2012


    【解决方案1】:

    这是我的解决方案。对此的想法是:

    1) 将所有日期四舍五入到当月的第一天,然后使用 (ID, StartDateRounded) 的不同数据集。从您的数据集中,结果应如下所示:

    ID     StartDateRounded
    
    1      2017-01-01
    1      2017-02-01
    2      2017-01-01
    2      2017-03-01
    3      2017-02-01
    3      2017-05-01
    

    2) 从这个合并的数据集中,按 ID 查找上个月没有记录的所有记录(这意味着它不是连续的月份,因此是新数据点的开始)。这是你的最终数据集

    with DatesTable AS 
    (
      SELECT DISTINCT ID
        ,DATEADD(month,DateDiff(month,0,StartDate),0) StartDateRounded
        ,DATEADD(month,DateDiff(month,0,StartDate)+1,0) StartDateRoundedPlusOne
      FROM Table1
    )
    SELECT t1.ID, DatePart(month,t1.StartDateRounded) AS StartDateMonth
      FROM DatesTable t1
        LEFT JOIN DatesTable t2
          ON t1.ID = t2.ID
            AND t1.StartDateRounded = t2.StartDateRoundedPlusOne
    WHERE t2.ID IS NULL; --Verify no record exists for prior month
    

    sqlfiddler 供参考。让我知道这是否有帮助

    【讨论】:

      【解决方案2】:

      只需要利用内部查询上的lag来比较行之间的值,并将有问题的逻辑应用于中间查询,然后进行最终选择。

      /*SAMPLE DATA*/
      create table #table1
          (
              ID int not null
              , StartDate date not null
              , EndDate date null
          )
      
      insert into #table1
      values (1, '2017-01-12', '2017-01-28')
          , (1, '2017-01-19', '2017-01-28')
          , (1, '2017-01-29', '2017-02-11')
          , (1, '2017-02-01', '2017-02-11')
          , (1, '2017-02-19', '2017-02-24')
          , (2, '2017-01-12', '2017-01-28')
          , (2, '2017-01-19', '2017-01-28')
          , (2, '2017-03-09', '2017-03-20')
          , (3, '2017-02-12', '2017-02-28')
          , (3, '2017-02-19', '2017-02-28')
          , (3, '2017-05-05', '2017-05-29')
          , (3, '2017-05-09', '2017-05-29')
      
      /*ANSWER*/
      
      --Final Select
      select c.ID
      , c.StartDateMonth
      from (
          --Compare record values to rule a record in/out based on OP's logic
          select b.ID
          , b.StartDateMonth
          , case when b.StartDateMonth = b.StartDateMonthPrev then 0 --still the same month?
                 when b.StartDateMonth = b.StartDateMonthPrev + 1 then 0 --immediately prior month?
                 when b.StartDateMonth = 1 and b.StartDateMonthPrev = 12 then 0 --Dec/Jan combo
                 else 1
            end as IncludeFlag
          from (
              --pull StartDateMonth of previous record into current record
              select a.ID
              , datepart(mm, a.StartDate) as StartDateMonth
              , lag(datepart(mm, a.StartDate), 1, NULL) over (partition by a.ID order by a.StartDate asc) as StartDateMonthPrev
              from #table1 as a
              ) as b
          ) as c
      where 1=1
      and c.IncludeFlag = 1
      

      输出:

      +----+----------------+
      | ID | StartDateMonth |
      +----+----------------+
      |  1 |              1 |
      |  2 |              1 |
      |  2 |              3 |
      |  3 |              2 |
      |  3 |              5 |
      +----+----------------+
      

      【讨论】:

        【解决方案3】:

        试试下面的查询,

        SELECT  ID,MIN(YEARMONTH) AS  YEARMONTH
        FROM    (
                SELECT  ID
                        ,YEAR([StartDate])*100+MONTH([StartDate])       AS YEARMONTH
                        ,LAG(YEAR([StartDate])*100+MONTH([StartDate])) 
                                                    OVER(ORDER BY ID)   AS PREVYEARMONTH
                        ,ROW_NUMBER() OVER(ORDER BY ID)                 AS ROW_NO
                FROM    @Table1
                GROUP BY ID,((YEAR([StartDate])*100)+MONTH([StartDate]))
        )   AS T
        GROUP BY ID
            ,(CASE WHEN YEARMONTH - PREVYEARMONTH > 1 THEN ROW_NO ELSE 0 END)
        ORDER BY ID
        

        输出:

        ID  YEARMONTH
        1   201701
        2   201701
        2   201703
        3   201702
        3   201705
        

        【讨论】:

          【解决方案4】:

          谢谢大家。大多数逻辑似乎都有效..但我只尝试了以下一个,我很擅长这个。

          SELECT t1.ID, DatePart(month,t1.Startdate) AS StartDateMonth
            FROM DatesTable t1
              LEFT JOIN DatesTable t2
                ON t1.ID = t2.ID
                  AND DatePart(month,t1.Startdate)  = DatePart(month,t2.Startdate)+1
          WHERE t2.ID IS NULL;
          

          再次感谢

          【讨论】:

          • 不完全 100% 确定您的最终目标是什么,但我感觉这个查询会在您接近年底时给您带来问题(特别是使用 DatePart(month,date))。在您的输入表中包含以下记录,并查看此查询是否返回您对 ID 4 的预期结果:(4, '2018-12-12', '2018-12-28'), (4, '2019-01- 19', '2019-01-28')
          【解决方案5】:

          好的,我没有检查就写了我的第一个查询,相信它会正常工作。这是我的更新版本,应该比其他解决方案更快

          select
              id
              , min(st)%12 --this will return start month
              , min(st)/12 + 1 --this will return year, just in case if you need it
          from (
              select
                  id, st, gr = st - row_number() over (partition by ID order by st)
              from (
                  select
                      distinct ID, st = (year(StartDate) - 1) * 12 + month(StartDate)
                  from
                      #table2
              ) t
          ) t
          group by id, gr
          

          【讨论】:

            猜你喜欢
            • 2020-05-15
            • 2016-01-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-29
            • 2023-03-25
            • 2012-12-20
            • 1970-01-01
            相关资源
            最近更新 更多