Сумма из N ненулевых предшествующих строк в таблице SQL - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть следующая таблица:

DATE, EMPLOYEE_ID, ILL
1.1.2016, 101, 0
1.1.2016, 102, 1
2.1.2016, 101, 1
2.1.2016, 102, 1
3.1.2016, 101, 0
3.1.2016, 102, 0

И мне нужно написать код SQL для создания нового столбца, который бы вычислял число предшествующих (с учетом DATE) ненулевых целых чисел в столбце ILL для нового столбца.

И это должно быть для каждого работника отдельно.

Причина в том, что мне нужно выяснить, сколько дней сотрудник заболел (1 за отсутствие в колонке ILL) до указанной даты.

Это вообще возможно сделать в SQL?

В настоящее время я пытаюсь изменить запрос с https://dba.stackexchange.com/questions/181773/sum-of-previous-n-number-of-columns-based-on-some-category но у меня пока нет успеха.

ВЫХОД Я ХОЧУ:

DATE, EMPLOYEE_ID, PREVIOUS
1.1.2016, 101, 0
1.1.2016, 102, 0
2.1.2016, 101, 0
2.1.2016, 102, 1
3.1.2016, 101, 1
3.1.2016, 102, 2
4.1.2016, 101, 0
4.1.2016, 102, 0

Это подготовка данных для моей магистерской диссертации. Я использую SAP HANA STUDIO.

Ответы [ 4 ]

0 голосов
/ 19 сентября 2018

Если вы хотите узнать количество последовательных плохих дней непосредственно перед текущей датой для сотрудника, можно использовать следующий SQL-запрос

with newdata as (
select 
    *,
    case 
        when ill = 1 and lag(ill,1,0) over (partition by EMPLOYEE_ID order by date) = 0 then 1 end as illdays
from testdata
), empdata as (
select
    date, EMPLOYEE_ID, ill,
    case when ill = 1 and lag(ill,1,0) over (partition by EMPLOYEE_ID order by date) = 1 then coalesce(lag(illdays,1,0) over (partition by EMPLOYEE_ID order by date),0)+1 else illdays end as illdays
from newdata
)
select
date, EMPLOYEE_ID, ill,
coalesce( lag(illdays,1,0) over (partition by EMPLOYEE_ID order by date), 0) as previous
from empdata
order by EMPLOYEE_ID, date;

Прежде чем углубляться в детали и объяснять SQL-запрос, вотвывод выполнения выше SqlScript

enter image description here

Прежде всего, вместо операторов выбора sub я использовал Common Table Expression выражение CTE вSQLScript с использованием предложений WITH

Я часто использовал функцию SQL Lag () в моем коде для чтения предыдущих записей в заданном порядке, используя предложения Partition By и Order By, следующие за функцией Lag ().Поскольку функция Lag () является стандартной функцией SQL, вы можете использовать ее на разных платформах баз данных

Запрос фактически находит начальную точку в newdata CTE и сохраняет столбец illdays.

Затем я обновляю этозначение в следующих empdata CTE.В этой части определяются повторяющиеся дни болезни, следующие один за другим

Последний CTE используется для отображения дней болезни и подготовки окончательного результата

Надеюсь, это поможет

0 голосов
/ 17 сентября 2018

Это можно сделать, назначив номер группы каждой группе, разделенной нулями. Затем вы должны использовать row_number() в группе.

Вы можете рассчитать номер группы, используя накопленную сумму. Итак, запрос выглядит так:

select t.*,
       (case when ill = 1
             then row_number() over (partition by employee_id, grp, ill order by date)
        end) as ill_day_counter
from (select t.*,
             sum(case when ill = 0 then 1 else 0 end) over (partition by employee_id order by date) as grp
      from t
     ) t;
0 голосов
/ 19 сентября 2018

Простое самостоятельное соединение поможет решить эту проблему, не используя только SUM () и GROUP BY следующим образом

select 
    t1.date, 
    t1.EMPLOYEE_ID, 
    t1.ill, 
    coalesce(sum(t2.ill),0) as previous
from testdata as t1
left join testdata as t2
    on t1.EMPLOYEE_ID = t2.EMPLOYEE_ID and
       t1.date > t2.date
group by t1.date, t1.EMPLOYEE_ID, t1.ill
order by t1.date, t1.EMPLOYEE_ID;

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

SELECT date,
       employee_id,
       ill, 
       coalesce(
       SUM(ill) OVER 
            (PARTITION BY employee_id
             ORDER BY date ASC
             ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
       ), 0) as Previous
FROM   testdata

Просто записка, как я понял из вашего вопроса; Вы, кажется, спрашиваете количество дней подряд, в течение которых работник болел до этого дня. Я прав?

0 голосов
/ 17 сентября 2018

Вы можете использовать совокупный (оконный) счет:

SELECT date,
       employee_id,
       ill, 
       COUNT(CASE ill WHEN 1 THEN 1 END) OVER 
            (PARTITION BY employee_id
             ORDER BY date ASC
             ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT_ROW)
FROM   mytable
...