显示所有日期范围的数据,包括缺失日期
Display data for all date ranges including missing dates
我对日期有疑问。我有一个 table,其中包含员工的起止日期。为了进行评估,我想显示每月的每个日期以及第二个 sql table.
的相应值
SQL Table:
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 之间的日期
非常感谢您!
它可能在您的 select 中,试试:
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
您的 CTE 只生成 31 个数字,因此它只显示 1 月的日期。
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
递归 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
您检查过 datefrom 和 dateto 是否在正确的范围内吗?
DateTime 字段的最小值为 1753-01-01,最大值为 9999-12-31。
查看您的来源 table 以检查初始值。
我对日期有疑问。我有一个 table,其中包含员工的起止日期。为了进行评估,我想显示每月的每个日期以及第二个 sql table.
的相应值SQL Table:
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 之间的日期
非常感谢您!
它可能在您的 select 中,试试:
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
您的 CTE 只生成 31 个数字,因此它只显示 1 月的日期。
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
递归 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
您检查过 datefrom 和 dateto 是否在正确的范围内吗?
DateTime 字段的最小值为 1753-01-01,最大值为 9999-12-31。
查看您的来源 table 以检查初始值。