Отображение периодического значения в новом столбце на основе значения другого столбца

Мне бы хотелось, чтобы запрос, основанный на поле "Периодичность", повторял бы каждые N строк значение True, сгруппированное по полю "Тип". Я думаю, что могу объяснить лучше на примере:

Имея следующую таблицу...

id  type periodicity
1   1    3
2   1    3
3   1    3
4   1    3
5   1    3
6   1    3
7   1    3
8   1    3
9   1    3
10  2    2
11  2    2
12  2    2
13  2    2
14  2    2
15  2    2
16  2    2

... Я хотел бы иметь запрос, который будет возвращать что-то вроде этого...

id  type periodicity    execute_operation
1   1    3              TRUE
2   1    3              FALSE
3   1    3              FALSE
4   1    3              TRUE
5   1    3              FALSE
6   1    3              FALSE
7   1    3              TRUE
8   1    3              FALSE
9   1    3              FALSE
10  2    2              TRUE
11  2    2              FALSE
12  2    2              TRUE
13  2    2              FALSE
14  2    2              TRUE
15  2    2              FALSE
16  2    2              TRUE

Для строк, где поле "тип" равно 1, поле "execute_operation" будет помечено как True каждые 3 строки (значение, определенное в поле "периодичность").

Для строк, имеющих "тип" равен 2, поле "execute_operation" будет помечено как True каждые 2 строки.

Как мне этого добиться?

3 ответа

Решение

Вы можете объединить оконную функцию ROW_NUMBER с оператором по модулю.

Порядковый номер последовательности каждой группы (1, 2, 3, ...). По модулю возвращается позиция в последовательности путем вычисления остатка. Пример:

1 Мод 3 = 1.

2 Mod 3 = 2.

3 Мод 3 = 0.

Если мод числа строк по периодичности равен 1, то возвращается значение true.

WITH [Sample] AS 
    (
        -- CTE provides sample data.
        SELECT
            *
        FROM
            (
                VALUES
                    (1,  1, 3),
                    (2,  1, 3),
                    (3,  1, 3),
                    (4,  1, 3),
                    (5,  1, 3),
                    (6,  1, 3),
                    (7,  1, 3),
                    (8,  1, 3),
                    (9,  1, 3),
                    (10, 2, 2),
                    (11, 2, 2),
                    (12, 2, 2),
                    (13, 2, 2),
                    (14, 2, 2),
                    (15, 2, 2),
                    (16, 2, 2)
            ) AS x(id, [type], periodicity)
    )
SELECT
    s.id,
    s.[type],
    s.periodicity,
    CASE ROW_NUMBER() OVER (PARTITION BY  s.[type] ORDER BY s.id) % periodicity
        WHEN 1 THEN 1
        ELSE 0
    END AS execute_operation
FROM
    [Sample] AS s
ORDER BY
    s.id
;

Я сделал, как показано ниже, для достижения требуемого результата. Вместо '%' (мод) вы можете сохранить периодичность. И я предположил, что ваш столбец идентификатора будет иметь последовательные номера, поэтому я использовал его из-за устранения row_number

    SELECT ID,
       TYPE,
       CASE
         WHEN RNO = 1
              AND TYPE = 1 THEN 'TRUE'
         WHEN RNO = 2
              AND TYPE = 2 THEN 'TRUE'
         ELSE 'FALSE'
       END STATUS
FROM   (SELECT ID,
               TYPE,
               CASE
                 WHEN TYPE = 1 THEN Replace(ID%3, 0, 3)
                 ELSE Replace(ID%2, 0, 2)
               END RNO
        FROM   #TABLE1)A 

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

update tbl_Sample set Operation = 0 --default to false

;WITH CTE
AS
(
select *
,ROW_NUMBER() over(Partition by Periodicity order by ID) 'R'
 from tbl_Sample

 )

 UPDATE CTE
 SET Operation = 1
 WHERE R%Periodicity = 1
Другие вопросы по тегам