【问题标题】:Increment column for streaks条纹的增量列
【发布时间】:2019-01-27 23:15:35
【问题描述】:

如何使以下结果以黄色突出显示?

基本上我想要一个计算字段,当 VeganOption = 1 时递增 1,当 VeganOption = 0 时为零

我尝试使用以下查询,但使用分区在零后继续递增。我有点卡在这个上。

SELECT [UniqueId]
      ,[Meal]
      ,[VDate]
      ,[VeganOption]
      , row_number() over (partition by [VeganOption] order by [UniqueId])
  FROM [Control]
  order by [UniqueId]

表格数据:

CREATE TABLE Control
    ([UniqueId] int, [Meal] varchar(10), [VDate] datetime, [VeganOption] int);

INSERT INTO Control ([UniqueId], [Meal], [VDate], [VeganOption])
VALUES
('1', 'Breakfast',' 2018-08-01 00:00:00', 1),
('2', 'Lunch',' 2018-08-01 00:00:00', 1),
('3', 'Dinner',' 2018-08-01 00:00:00', 1),
('4', 'Breakfast',' 2018-08-02 00:00:00', 1),
('5', 'Lunch',' 2018-08-02 00:00:00', 0),
('6', 'Dinner',' 2018-08-02 00:00:00', 0),
('7', 'Breakfast',' 2018-08-03 00:00:00', 1),
('8', 'Lunch',' 2018-08-03 00:00:00', 1),
('9', 'Dinner',' 2018-08-03 00:00:00', 1),
('10', 'Breakfast',' 2018-08-04 00:00:00', 0),
('11', 'Lunch',' 2018-08-04 00:00:00', 1),
('12', 'Dinner',' 2018-08-04 00:00:00', 1)
;

这适用于 SQL Server 2016+

【问题讨论】:

  • 我知道赞成票表明了这一点,但很高兴看到一个精心设计的问题,包括样本数据、预期结果、尝试,然后在 CREATE 和 @987654326 @ 陈述。谢谢你。 :)
  • @Larnu 而不是通常的琐碎转换从 varchar 到 datetime 对于 chagne :-)
  • 真正困扰我的是“如何拆分这个分隔列表”问题@ZoharPeled。这么多……哈哈

标签: sql sql-server tsql sql-server-2016 gaps-and-islands


【解决方案1】:

您可以使用SUM 创建子组,然后使用ROW_NUMBER

WITH cte AS (
  SELECT [UniqueId]
      ,[Meal]
      ,[VDate]
      ,[VeganOption]
      ,sum(CASE WHEN VeganOption = 1 THEN 0 ELSE 1 END) 
         over (order by [UniqueId]) AS grp  --switching 0 <-> 1
  FROM [Control]
)
SELECT *,CASE WHEN VeganOption =0 THEN 0
        ELSE ROW_NUMBER() OVER(PARTITION BY veganOption, grp ORDER BY [UniqueId])
        END AS VeganStreak                  -- main group and calculated subgroup
FROM cte
order by [UniqueId];

Rextester Demo

【讨论】:

  • 我喜欢这种方法,比其他处理间隙和孤岛的传统方法更容易理解。
【解决方案2】:

这是间隙和岛屿的变体。

我喜欢使用行号的差异来定义条纹。这看起来像

select c.*,
       (case when veganoption = 1
             then row_number() over (partition by veganoption, seqnum - seqnum_v order by uniqueid)
             else 0
        end) as veganstreak
from (select c.*,
             row_number() over (partition by veganoption order by uniqueid) as seqnum_v,
             row_number() over (order by uniqueid) as seqnum
      from c
     ) c;

为什么这行得通有点难以解释。但是,如果您查看子查询的结果,您将看到行号的差异如何定义您想要识别的条纹。其余的只是应用row_number() 来列举餐点。

这是Rextester

【讨论】:

  • 它产生不正确的结果:rextester.com/YDVD78565。最后两行 (4,5) 而不是 (1,2)
  • @LukaszSzozda 。 . .谢谢你把它放在一起。我没有注意到日期不是唯一的。 uniqueid 是用于逻辑的正确列。
【解决方案3】:

一种方法是使用 CTE 来定义您的分组,然后对这些分组执行进一步的ROW_NUMBER(),结果是:

WITH Grps AS(
    SELECT *,
           ROW_NUMBER() OVER (ORDER BY UniqueID ASC) - 
           ROW_NUMBER() OVER (PARTITION BY VeganOption ORDER BY UniqueID ASC) AS Grp
    FROM Control)
SELECT *,
       CASE VeganOption WHEN 0 THEN 0 ELSE ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY UniqueID ASC) END
FROM Grps
ORDER BY UniqueId;

【讨论】:

  • 您应该将 VeganOption = 0 rextester.com/COTWN74238 归零。第 5,6 行应该是 (0,0) 而不是 (1,2)。第 10 行相同。
猜你喜欢
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
相关资源
最近更新 更多