我正在根据另一个表中包含的值填充一个带有日期的表。
Source : tblA
dtFrom dtTo
2019-01-01 2019-01-03
2019-02-01 2019-02-02
2019-03-01 2019-03-01
Destination : tblB
sDate
2019-01-01
2019-01-02
2019-01-03
2019-02-01
2019-02-02
2019-03-01
SQL Server2014。一如既往,在此先感谢:-)
答案 0 :(得分:2)
您可以使用递归CTE:
with dates as (
select dtfrom as dt, dtto
from tblA
union all
select dateadd(day, 1, dt), dtto
from dates
where dt < dtto
)
insert tblB (sDate)
select distinct dt
from dates;
select distinct
仅在处理重叠期间是必需的。如果您知道没有重叠,那就不要使用它。
答案 1 :(得分:0)
您可以使用union
将两列中的值合并为一个行集:
insert tblB
(sDate)
select distinct dt
from (
select dtFrom as dt
from tblA
union all
select dtTo
from tblA
) s
答案 2 :(得分:0)
使用始终方便使用的Calendar Table,该表在特定年份之间的所有天中每天都有1行。您可以添加诸如IsBusinessDay
或WorkingStartHour
/ WorkingEndHour
之类的其他列,以使日期查询更加轻松。
-- Create Calendar Table
DECLARE @StartDate DATE = '2000-01-01'
DECLARE @EndDate DATE = '2050-01-01'
SET DATEFIRST 1 -- 1: Monday, 7: Sunday
CREATE TABLE CalendarTable (
Date DATE PRIMARY KEY,
IsWorkingDay BIT
-- Other columns you might need
)
;WITH RecursiveCTE AS
(
SELECT
Date = @StartDate
UNION ALL
SELECT
Date = DATEADD(DAY, 1, R.Date)
FROM
RecursiveCTE AS R
WHERE
DATEADD(DAY, 1, R.Date) <= @EndDate
)
INSERT INTO CalendarTable (
Date,
IsWorkingDay)
SELECT
Date = R.Date,
IsWorkingDay = CASE WHEN DATEPART(WEEKDAY, R.Date) BETWEEN 1 AND 5 THEN 1 ELSE 0 END
FROM
RecursiveCTE AS R
OPTION
(MAXRECURSION 0)
现在有了日历表,只需将BETWEEN
和INSERT
加入目标表即可。您可以使用DISTINCT
来确保日期不会重复:
INSERT INTO tblB (
sDate)
SELECT DISTINCT
sDate = C.Date
FROM
tlbA AS A
INNER JOIN CalendarTable AS C ON C.Date BETWEEN A.dtFrom AND A.dtTo
例如,假设您只想插入工作日(星期一至星期五)的记录。您只需要过滤日历表并完成。您可以在表上添加所需的任何逻辑,并在使用时对其进行过滤,而无需重复复杂的日期时间逻辑。
INSERT INTO tblB (
sDate)
SELECT DISTINCT
sDate = C.Date
FROM
tlbA AS A
INNER JOIN CalendarTable AS C ON C.Date BETWEEN A.dtFrom AND A.dtTo
WHERE
C.IsWorkingDay = 1
答案 3 :(得分:0)
使用日历,您可以在范围上进行内部联接以产生Insert语句。
DECLARE @StartDate DATETIME = (SELECT MIN(dtFrom) FROM tblA)
DECLARE @EndDate DATETIME = (SELECT MAX(dtTo) FROM tblB)
;WITH Calendar as
(
SELECT CalendarDate = @StartDate, CalendarYear = DATEPART(YEAR, @StartDate), CalendarMonth = DATEPART(MONTH, @StartDate)
UNION ALL
SELECT CalendarDate = DATEADD(MONTH, 1, CalendarDate), CalendarYear = DATEPART(YEAR, CalendarDate), CalendarMonth = DATEPART(MONTH, CalendarDate)
FROM Calendar WHERE DATEADD (MONTH, 1, CalendarDate) <= @EndDate
)
INSERT INTO tblB
SELECT DISTINCT
C.CalendarDate
FROM
Calendar C
INNER JOIN tblA A ON C.CalendarDate BETWEEN A.dtFrom AND A.dtTo
答案 4 :(得分:0)
您可以通过使用以下查询来获得此结果。
步骤1-创建一个自定义函数,它将日期范围作为参数并返回日期序列。
oneResult
第2步-将此自定义函数与表tblA结合在一起,并根据需要将记录插入tblb中
CREATE FUNCTION [dbo].[GenerateDateRange]
(@StartDate AS DATE,
@EndDate AS DATE,
@Interval AS INT
)
RETURNS @Dates TABLE(DateValue DATE)
AS
BEGIN
DECLARE @CUR_DATE DATE
SET @CUR_DATE = @StartDate
WHILE @CUR_DATE <= @EndDate BEGIN
INSERT INTO @Dates VALUES(@CUR_DATE)
SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE)
END
RETURN;
END;