当我从提供时,我想返回当前正在旅行的所有旅行者和日期。意思是如果我从1 Jan 2022出发直到2022年1月10日我提供了一个From日期2022年1月5日和到日期2022年1月15日我必须回来,因为我在那段时间旅行。因此在下面的代码中,必须返回Mike。
DECLARE @DateFrom DATE = '2022-01-05',
@DateTo DATE = '2022-01-15'
DROP TABLE IF EXISTS #Dates
CREATE TABLE #Dates
(
DepartureDate Date NULL,
ReturnDate Date NULL,
Name VARCHAR(8) NULL
)
INSERT INTO #Dates (DepartureDate, ReturnDate, Name)
VALUES ('2022-01-01', '2022-01-10', 'Mike' )
SELECT *
FROM #Dates
WHERE DepartureDate >= @DateFrom
AND ReturnDate <= @DateTo
如果您选择的日期范围在'2021-12-01'和'2021-12-05'之间,则Mike没有旅行,因此不应返回。但是,如果您选择的日期范围在'2022-01-05'和'2022-01-15'之间,则应该返回Mike,因为Mike确实在该日期范围内旅行,即使他没有旅行所有的日子。
重叠区间问题!检查每个间隔是否在另一个间隔结束前开始:
SELECT *
FROM #Dates
WHERE DepartureDate <= @DateTo
AND ReturnDate >= @DateFrom
我想你的问题是你的WHERE
条款并不适用于所有情况来支持你的问题描述。
你可以这样写来修复它:
SELECT *
FROM #Dates
WHERE
(DepartureDate >= @DateFrom AND ReturnDate <= @DateTo) -- Traveled only between provided date range
OR (DepartureDate < @DateFrom AND ReturnDate > @DateTo) -- Traveled the entire date range, possibly longer
OR (DepartureDate < @DateFrom AND ReturnDate <= @DateTo AND ReturnDate >= @DateFrom) -- Started traveling before date range but finished traveling within it
OR (DepartureDate >= @DateFrom AND DepartureDate <= @DateTo AND ReturnDate > @DateTo) -- Started traveling within the date range but finished traveling after
请看每个案例的注释。
或者你也可以把它写成4个SELECT
语句(每种情况一个)和一个UNION ALL
子句。有时,SQL Server引擎在以这种方式编写查询时产生更有效的查询计划,而不是多个OR
谓词:
-- Traveled only between provided date range
SELECT *
FROM #Dates
WHERE
DepartureDate >= @DateFrom
AND ReturnDate <= @DateTo
UNION ALL
-- Traveled the entire date range, possibly longer
SELECT *
FROM #Dates
WHERE
DepartureDate < @DateFrom
AND ReturnDate > @DateTo
UNION ALL
-- Started traveling before date range but finished traveling within it
SELECT *
FROM #Dates
WHERE
DepartureDate < @DateFrom
AND ReturnDate <= @DateTo
AND ReturnDate >= @DateFrom
UNION ALL
-- Started traveling within the date range but finished traveling after
SELECT *
FROM #Dates
WHERE
DepartureDate >= @DateFrom
AND DepartureDate <= @DateTo
AND ReturnDate > @DateTo
你必须测试两种方法,看看哪一种对你的特定情况表现更好。
旁注,不要使用SELECT *
,因为它是一个反模式。相反,您应该显式地列出查询所需的列。