Способ найти данные таблицы SQL с тем же статусом в течение 3 дней подряд - PullRequest
0 голосов
/ 20 мая 2018

У меня есть таблица SQL, например, ниже

Code Name    DayStatus  Date
101  John    A          20-May-2018
101  John    A          19-May-2018
101  John    A          18-May-2018
102  Karl    A          20-May-2018
102  Karl    A          19-May-2018
102  Karl    P          18-May-2018
103  Lorem   P          20-May-2018
103  Lorem   A          19-May-2018
103  Lorem   A          18-May-2018
104  Ipsum   A          20-May-2018
104  Ipsum   P          19-May-2018
104  Ipsum   A          18-May-2018
105  Milton  A          20-May-2018
105  Milton  A          19-May-2018
105  Milton  A          18-May-2018
107  Saleh   A          20-May-2018
107  Saleh   A          19-May-2018
107  Saleh   W          18-May-2018
107  Saleh   A          17-May-2018
108  Virat   A          20-May-2018
108  Virat   H          19-May-2018
108  Virat   A          18-May-2018
108  Virat   A          17-May-2018

Здесь «A» означает «Отсутствует», «P» означает настоящее, «H» означает «Праздник», «W» означает «слабый»выкл.

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

Для virat иSaleh также будет считаться последовательным отсутствием. Но если P (присутствует) появится между последовательными днями, то это не будет считаться последовательным отсутствием.

Ожидаемый результат должен быть --- *

Code Name    
101  John          
105  Milton          
107  Saleh             
108  Virat       

Ответы [ 5 ]

0 голосов
/ 21 мая 2018

вы можете попробовать это:

DECLARE @CurrentDate DATETIME='2018-05-20'  --CAST(GETDATE() AS DATE)


;with cte
 AS
  (
    SELECT [Code],Name,DayStatus,lag(daystatus) over (partition by code order by date) as ds_1,
         lag(daystatus, 2) over (partition by code order by date) as ds_2,
        lag(daystatus, 3) over (partition by code order by date) as ds_3 
    FROM Table1 
    WHERE [Date]<=@CurrentDate AND [Date]>=DATEADD(d,-3,@CurrentDate)
  )

SELECT [Code],Name FROM cte
WHERE daystatus = 'A' 
and (
     (ds_1 ='A' AND ds_2='A' AND (ds_3 in ('A','W','H') OR ds_3 IS NULL))
        OR
     (ds_1 ='A' AND ds_2 in ('A','W','H') AND ds_3 ='A')
        OR
     (ds_1 in ('A','W','H') AND ds_2='A'  AND ds_3 ='A')
  )

SQL Fiddle: http://sqlfiddle.com/#!18/7c124/42

0 голосов
/ 20 мая 2018

Другие ответы кажутся такими сложными.Я бы просто использовал lag():

select t.*
from (select t.*,
             lag(daystatus) over (partition by code order by date) as ds_1,
             lag(daystatus, 2) over (partition by code order by date) as ds_2

      from t
     ) t
where daystatus = 'A' and ds_1 = 'A' and ds_2 = 'A';

Если вам нужны только имена, а не даты:

select distinct name, code
from (select t.*,
             lag(daystatus) over (partition by code order by date) as ds_1,
             lag(daystatus, 2) over (partition by code order by date) as ds_2

      from t
     ) t
where daystatus = 'A' and ds_1 = 'A' and ds_2 = 'A';

Если вы хотите статус текущего дня, просто добавьте date = current_date к внешнему запросу.

0 голосов
/ 20 мая 2018

Вы можете использовать GROUP BY с предложением HAVING и "условным агрегатом"

например

SELECT Code, Name
FROM [table1]
GROUP BY Code, Name
HAVING COUNT( CASE WHEN Date BETWEEN CAST( DATEADD( DAY, -2, GETDATE()) AS DATE ) AND CAST( GETDATE() AS DATE ) AND DayStatus <> 'P' THEN 1 ELSE NULL END ) = 3

Что делает запрос HAVING:

  1. Подсчитывает количество записей / дней между сегодняшним днем ​​(включительно) и 3 днями ранее.
  2. Запись считается только тогда, когда `DayStatus <> 'P'
  3. Имя будет включено, только если3 дня можно посчитать
0 голосов
/ 20 мая 2018
with cte as
 (
   select *
      -- cumulative Max, returns 0 as long as there's no P status
     ,max(CASE WHEN DayStatus = 'P' THEN 1 ELSE 0 END)
      over (partition by code
            order by date desc) as mx
      -- status of the latest date
     ,first_value(DayStatus)
      over (partition by code
            order by date desc) as fv
   from Table1
 )
select code, name, count(*) as absentDays
from cte
where fv = 'A'   -- current status = 'A'
  and mx = 0     -- all rows before the 1st 'P'
group by code, name
having
   -- at least three days absent
   count(*) >= 3;

См. fiddle

Это можно легко изменить, чтобы работать, если для кода / дня не существует строки для расчета разницы дат между максимальным и минимальным (дата)

0 голосов
/ 20 мая 2018

Попробуйте выполнить запрос из этой демоверсии

SELECT code, name, count(*) absent_days
FROM (
  SELECT *,
        sum( xx ) over (partition by code order by date ) ss
  FROM (
    SELECT *,
          case when DayStatus = lag(DayStatus) over(partition by code order by Date)
               then 0 else 1
          end as xx
    FROM table1
    WHERE DayStatus not in( 'W','H')
  ) x
) y
WHERE DayStatus = 'A'
GROUP BY code, name, ss
HAVING count(*) >=3
order by code

| code |   name |     absent_days |
|------|--------|-----------------|
|  101 |   John |               3 |
|  105 | Milton |               3 |
|  107 |  Saleh |               3 |
|  108 |  Virat |               3 |

Эта версия содержит количество дней и дату начала каждого периода

    SELECT code, name, count(*) absent_days, min(date) from_date
    FROM (
      SELECT *,
            sum( xx ) over (partition by code order by date ) ss
      FROM (
        SELECT *,
              case when DayStatus = lag(DayStatus) over(partition by code order by Date)
                   then 0 else 1
              end as xx
        FROM table1
        WHERE DayStatus not in( 'W','H')
      ) x
    ) y
    WHERE DayStatus = 'A'
    GROUP BY code, name, ss
    HAVING count(*) >=3
    order by code

| code |   name | absent_days |            from_date |
|------|--------|-------------|----------------------|
|  101 |   John |           3 | 2018-05-18T00:00:00Z |
|  105 | Milton |           3 | 2018-05-18T00:00:00Z |
|  107 |  Saleh |           3 | 2018-05-17T00:00:00Z |
|  108 |  Virat |           3 | 2018-05-17T00:00:00Z |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...