Sql 条纹的增量列
如何获得以下以黄色突出显示的结果? 基本上,我想要一个计算字段,当VeganOption=1时,该字段递增1,当VeganOption=0时,该字段为零 我尝试过使用下面的查询,但是使用分区在0之后继续递增。我在这件事上有点纠结Sql 条纹的增量列,sql,sql-server,tsql,sql-server-2016,gaps-and-islands,Sql,Sql Server,Tsql,Sql Server 2016,Gaps And Islands,如何获得以下以黄色突出显示的结果? 基本上,我想要一个计算字段,当VeganOption=1时,该字段递增1,当VeganOption=0时,该字段为零 我尝试过使用下面的查询,但是使用分区在0之后继续递增。我在这件事上有点纠结 SELECT [UniqueId] ,[Meal] ,[VDate] ,[VeganOption] , row_number() over (partition by [VeganOption] order by [Un
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+的,这是关于间隙和孤岛的变体 我喜欢用行号的差来定义条纹。这看起来像
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来枚举膳食
这里有一种方法。一种方法是使用CTE定义分组,然后对这些分组进行进一步的行编号,从而产生:
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;
您可以使用SUM和ROW_编号创建子组:
它产生不正确的结果:。最后两行是4,5,而不是1,2@LukaszSzozda . . . 谢谢你把这些放在一起。我没有注意到日期不是唯一的。uniqueid是用于逻辑的正确列。我喜欢这种方法,它比其他传统的缺口和孤岛方法更容易理解。你应该将VeganOption设为0=0。第5,6行应为0,0,而不是1,2。第10行也是如此。我知道上面的投票显示了这一点,但看到一个精心设计的问题,有样本数据、预期结果、尝试,然后再加上CREATE和INSERT语句,真是太好了。谢谢@Larnu,而不是一个chagne从varchar到datetime的普通转换失败:-真正困扰我@ZoharPeled的是如何拆分这个分隔列表问题。这么多人。。。。英雄联盟
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];