Как получить следующий результат, выделенный желтым цветом? введите описание изображения здесь

По сути, я хочу вычисляемое поле, которое увеличивается на 1, когда VeganOption = 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+

12
pathDongle 21 Авг 2018 в 20:54

3 ответа

Лучший ответ

Вы можете создать подгруппы, используя 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

6
Lukasz Szozda 21 Авг 2018 в 18:03

Один из методов - использовать 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;
3
Larnu 21 Авг 2018 в 18:11

Это вариант на островках и разрывах.

Мне нравится определять полосы, используя разницу номеров строк. Это выглядит как

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.

3
Gordon Linoff 22 Авг 2018 в 01:42
51954221