如何选择最大日期早于某个值的行
Posted
技术标签:
【中文标题】如何选择最大日期早于某个值的行【英文标题】:How to select rows with max date older then some value 【发布时间】:2020-05-12 18:59:49 【问题描述】:我有 Microsoft SQL Server 2008 和一个包含如下数据的表:
id | file_date [datatime] | file_path [varchar(255)]
____________________________________________________
1 | 01-01-1999 | C:\f1.txt
2 | 01-01-2020 | C:\f2.txt
3 | 05-05-1999 | C:\f3.txt
4 | 05-05-2020 | C:\f3.txt
5 | 05-05-1999 | C:\f4.txt
6 | 06-05-1999 | C:\f4.txt
我需要选择所有 file_paths,其中 file_date 是旧的,并且没有其他具有此 file_path 的行具有较新的 file_date强>存在
例如,如果我必须获取日期早于 2019 年的行,我的结果应该是这样的:
file_path
C:\f1.txt
C:\f4.txt
我有一个解决方案:
SELECT rslt.file_path
FROM mytable rslt
GROUP BY rslt.file_path
HAVING MAX(rslt.file_date) < '2019-01-01'
问题是这个脚本需要大约 2 分钟才能返回一个表中的大约 62k 行,其中我有 4460 万行,而简单的脚本来获取所有早于日期的行(见下文)需要 2-3秒
SELECT * FROM mytable WHERE file_date < '2019-01-01'
那么,有什么办法可以优化我的解决方案吗?
【问题讨论】:
【参考方案1】:这需要多长时间?
SELECT t.file_path
FROM mytable t
WHERE NOT EXISTS (SELECT 1
FROM mytable t2
WHERE t2.file_path = t.file_path AND t2.file_date >= '2019-01-01'
);
您希望在(file_path, file_date)
上建立索引以获得最佳性能。
【讨论】:
【参考方案2】:您能否否定第二个更快的查询并执行NOT IN
?
SELECT rslt.file_path
FROM mytable rslt
WHERE rslt.file_path NOT IN
(SELECT rslt2.file_path
FROM mytable rslt2
WHERE rslt2.file_path IS NOT NULL
AND rslt2.file_date >= '2019-01-01')
GROUP BY rslt.file_path;
NOT IN
似乎会在选择拉回空值时变得有点古怪,所以我也在内部查询的 where 中放了一个 IS NOT NULL
,但你可能没有必要这样做。
【讨论】:
【参考方案3】:DECLARE @TargetDate date = '01-01-2019'
DECLARE @PathList TABLE (id int, file_date datetime, file_path varchar(255))
INSERT INTO @PathList VALUES
(1, '01-01-1999', 'C:\f1.txt')
, (2, '01-01-2020', 'C:\f2.txt')
, (3, '05-05-1999', 'C:\f3.txt')
, (4, '05-05-2020', 'C:\f3.txt')
, (5, '05-05-1999', 'C:\f4.txt')
, (6, '06-05-1999', 'C:\f4.txt')
;
SELECT DISTINCT
PL.file_path
FROM @PathList PL
LEFT JOIN @PathList PH ON PH.file_path = PL.file_path
AND PH.file_date >= @TargetDate
WHERE
PL.file_date < @TargetDate
AND PH.id IS NULL
【讨论】:
JOIN 的诀窍是:排除那些路径相同但日期较新的路径。【参考方案4】:检查一下
SELECT rslt.file_path, MAX(rslt.file_date) as Max_file_date
into #t
FROM mytable rslt
GROUP BY rslt.file_path
Select file_path
From #t
Where Max_file_date < '2019-01-01'
或者试试
SELECT rslt.file_path
into #t
FROM mytable rslt
WHERE file_date < '2019-01-01'
GROUP BY rslt.file_path
【讨论】:
以上是关于如何选择最大日期早于某个值的行的主要内容,如果未能解决你的问题,请参考以下文章