Отображение данных для всех диапазонов дат, включая пропущенные даты - PullRequest
0 голосов
/ 30 апреля 2019

У меня проблема с датами. У меня есть таблица с данными от и до даты для сотрудника. Для оценки я хотел бы отобразить каждую дату месяца с соответствующими значениями из второй таблицы sql.

Таблица SQL:

EmpNr | datefrom   | dateto     | hours
 0815 | 01.01.2019 | 03.01.2019 | 15
 0815 | 05.01.2019 | 15.01.2019 | 15
 0815 | 20.01.2019 | 31.12.9999 | 40

Данный сотрудник (0815) работал с 01.01.-15.01. 15 часов, а в течение 20.01.-31.01. 40 часов

Я бы хотел получить следующий результат:

0815 | 01.01.2019 | 15
0815 | 02.01.2019 | 15
0815 | 03.01.2019 | 15
0815 | 04.01.2019 | NULL
0815 | 05.01.2019 | 15
...
0815 | 15.01.2019 | 15
0815 | 16.01.2019 | NULL
0815 | 17.01.2019 | NULL
0815 | 18.01.2019 | NULL
0815 | 19.01.2019 | NULL
0815 | 20.01.2019 | 40
0815 | 21.01.2019 | 40
...
0815 | 31.01.2019 | 40

Что касается дат, у нас есть:

declare @year int = 2019, @month int = 1;
WITH numbers
as
(
    Select 1 as value
    UNion ALL
    Select value + 1 from numbers
    where value + 1 <= Day(EOMONTH(datefromparts(@year,@month,1)))
)
SELECT b.empnr, b.hours, datefromparts(@year,@month,numbers.value) Datum FROM numbers left outer join 
emptbl b  on b.empnr = '0815' and  (datefromparts(@year,@month,numbers.value) >=  b.datefrom and datefromparts(@year,@month,numbers.value) <= case b.dateto )

, который работает довольно хорошо, но у меня есть странная проблема, что этот код соответствует только датам с 01.01.2019 по 03.01.2019

Большое спасибо заранее!

Ответы [ 4 ]

1 голос
/ 30 апреля 2019

Вы проверяли, находится ли datefrom и dateto в правильном диапазоне?

Минимальное значение поля DateTime равно 1753-01-01, а максимальное значение равно 9999-12-31.

Посмотритев исходной таблице, чтобы проверить начальные значения.

1 голос
/ 30 апреля 2019

Рекурсивный CTE должен начинаться с MIN(datefrom) и MAX(dateto):

DECLARE @t TABLE (empnr INT, datefrom DATE, dateto DATE, hours INT);

INSERT INTO @t VALUES
(815, '2019-01-01', '2019-01-03', 15),
(815, '2019-01-05', '2019-01-15', 15),
(815, '2019-01-20', '9999-01-01', 40),
-- another employee
(999, '2018-01-01', '2018-01-31', 15),
(999, '2018-03-01', '2018-03-31', 15),
(999, '2018-12-01', '9999-01-01', 40);

WITH rcte AS (
    SELECT empnr
         , MIN(datefrom) AS refdate
         , ISNULL(NULLIF(MAX(dateto), '9999-01-01'), CURRENT_TIMESTAMP) AS maxdate -- clamp year 9999 to today
    FROM @t
    GROUP BY empnr

    UNION ALL

    SELECT empnr
         , DATEADD(DAY, 1, refdate)
         , maxdate
    FROM rcte
    WHERE refdate < maxdate
)
SELECT rcte.empnr
     , rcte.refdate
     , t.hours
FROM rcte
LEFT JOIN @t AS t ON rcte.empnr = t.empnr AND rcte.refdate BETWEEN t.datefrom AND t.dateto
ORDER BY rcte.empnr, rcte.refdate
OPTION (MAXRECURSION 1000) -- approx 3 years

Демонстрация на db <> fiddle

0 голосов
/ 30 апреля 2019

Ваш CTE производит только 31 число и, следовательно, показывает только январские даты.

declare @year int = 2019, @month int = 1;

WITH numbers
as
(
    Select 1 as value
    UNion ALL
    Select value + 1 from numbers
    where value + 1 <= Day(EOMONTH(datefromparts(@year,@month,1)))
)
SELECT *
FROM numbers

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=a24e58ef4ce522d3ec914f90907a0a9e

Вы можете попробовать ниже код,

with t0 (i)    as (select 0  union all  select 0  union all  select 0),
     t1 (i)    as (select a.i from t0 a ,t0 b ),
     t2 (i)    as (select a.i from t1 a ,t1 b ),
     t3 (srno) as (select row_number()over(order by a.i) from t2 a ,t2 b ),
     tbldt(dt) as (select dateadd(day,t3.srno-1,'01/01/2019') from t3)   
select  tbldt.dt 
from tbldt
where tbldt.dt <= b.dateto -- put your condition here

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=b16469908b323b8d1b98d77dd09bab3d

0 голосов
/ 30 апреля 2019

Это может быть на ваш выбор, попробуйте:

SELECT b.empnr, b.hours, datefromparts(@year,@month,numbers.value) Datum
FROM numbers 
LEFT OUTER JOIN emptbl b ON b.empnr = '0815' AND 
datefromparts(@year,@month,numbers.value) BETWEEN b.datefrom AND b.dateto 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...