CSj*_*kie 2 sql sql-server-2008
我是 SQL 新手,有一个包含 ID 和服务日期的大型数据库,我需要编写一个查询来为我提供每个 ID 提供服务的第一个日期。
我试过:
SELECT dbo.table.ID, dbo.otherTable.ServiceDate AS EasliestDate
FROM dbo.table INNER JOIN dbo.table.ID = dbo.otherTable.ID
Run Code Online (Sandbox Code Playgroud)
但是输出是每个 ID 的每个服务,其中有太多的结果需要排序。我希望输出只显示 ID 和最早的服务日期。任何建议表示赞赏。
编辑:更准确地说,如果最早的服务日期在我指定的年份内,我要查找的输出是 ID 和服务日期。IE 如果 ID = 1 在 2015 年和 2016 年有一项服务,而我正在搜索 2016 年的 ID,那么 ID = 1 不应出现在结果中,因为 2015 年有一项较早的服务。
编辑:感谢所有对此提供帮助的人!我接受的答案完全符合我的要求。尽管 Patty 详细说明了如何按年进一步过滤结果,但要向 Patty 致敬。
SELECT dbo.table.ID,
MIN(dbo.otherTable.ServiceDate) AS EasliestDate
FROM dbo.table
INNER JOIN otherTable
ON dbo.table.ID = dbo.otherTable.ID
GROUP BY dbo.table.ID;
Run Code Online (Sandbox Code Playgroud)
附录
参考评论中的一个问题:
我如何限制它只显示那些在特定年份提供服务的人?
这将取决于您的确切要求,请考虑以下设置:
ID ServiceDate
--------------------
1 2014-05-01
1 2015-08-01
1 2016-07-07
2 2015-08-19
Run Code Online (Sandbox Code Playgroud)
如果您指定的年份是 2016 年,您只希望包含 ID = 1,但假设您仍想返回第一个日期,2014-05-01那么您需要添加一个带有 case 语句的带有子句来获取它。
DECLARE @Year INT = 2016;
DECLARE @YearStart DATE = DATEADD(YEAR, @Year - 1900, '19000101'),
@YearEnd DATE = DATEADD(YEAR, @Year - 1900 + 1, '19000101');
SELECT @YearStart, @YearEnd
SELECT t.ID,
MIN(o.ServiceDate) AS EasliestDate
FROM dbo.table AS t
INNER JOIN otherTable AS o
ON o.ID = r.ID
GROUP BY t.ID
HAVING COUNT(CASE WHEN o.ServiceDate >= @YearStart
AND o.ServiceDate < @YearEnd THEN 1 END) > 0;
Run Code Online (Sandbox Code Playgroud)
如果您只想要 2016 年的最早日期,则 a where 子句就足够了
DECLARE @Year INT = 2016;
DECLARE @YearStart DATE = DATEADD(YEAR, @Year - 1900, '19000101'),
@YearEnd DATE = DATEADD(YEAR, @Year - 1900 + 1, '19000101');
SELECT @YearStart, @YearEnd
SELECT t.ID,
MIN(o.ServiceDate) AS EasliestDate
FROM dbo.table AS t
INNER JOIN otherTable AS o
ON o.ID = r.ID
WHERE o.ServiceDate >= @YearStart
AND o.ServiceDate < @YearEnd
GROUP BY t.ID;
Run Code Online (Sandbox Code Playgroud)
值得注意的是有一个很好的理由我选择计算年初和明年的开始并使用
WHERE o.ServiceDate >= @YearStart
AND o.ServiceDate < @YearEnd
Run Code Online (Sandbox Code Playgroud)
而不是仅仅
WHERE DATEPART(YEAR, o.ServiceDate) = 2016;
Run Code Online (Sandbox Code Playgroud)
在前者中,ServiceDate可以使用索引,而在后者中,DATEPART必须对每条记录进行计算,这可能会导致严重的性能问题。
附录 2
要执行以下操作:
我想要的确切内容是最早服务在我指定年份的 ID。
然后你需要一个带有条款,只是与我之前发布的不同:
DECLARE @Year INT = 2016;
DECLARE @YearStart DATE = DATEADD(YEAR, @Year - 1900, '19000101'),
@YearEnd DATE = DATEADD(YEAR, @Year - 1900 + 1, '19000101');
SELECT @YearStart, @YearEnd
SELECT t.ID,
MIN(o.ServiceDate) AS EasliestDate
FROM dbo.table AS t
INNER JOIN otherTable AS o
ON o.ID = r.ID
GROUP BY t.ID
HAVING MIN(o.ServiceDate) >= @YearStart
AND MIN(o.ServiceDate) < @YearEnd;
Run Code Online (Sandbox Code Playgroud)
附录 3
CREATE VIEW dbo.YourView
AS
SELECT dbo.table.ID,
MIN(dbo.otherTable.ServiceDate) AS EasliestDate
FROM dbo.table
INNER JOIN otherTable
ON dbo.table.ID = dbo.otherTable.ID
GROUP BY dbo.table.ID;
Run Code Online (Sandbox Code Playgroud)
然后您可以将您的条件应用于视图:
SELECT *
FROM dbo.YourView
WHERE EasliestDate >= '2015-01-01'
AND EasliestDate < '2016-01-01';
Run Code Online (Sandbox Code Playgroud)