我是SQL的新手,拥有一个包含ID和服务日期的大型数据库,我需要编写一个查询,以便为每个ID提供服务的第一个日期。
我试过了:
SELECT dbo.table.ID, dbo.otherTable.ServiceDate AS EasliestDate
FROM dbo.table INNER JOIN dbo.table.ID = dbo.otherTable.ID
但是输出是每个ID的每个服务,其结果太多而无法排序。我希望输出只显示ID和最早的服务日期。任何建议都表示赞赏。
编辑:更确切地说,如果最早的服务日期是我指定的年份,我要查找的输出是ID和服务日期。 I.E.如果ID = 1在2015年和2016年有服务且我在2016年搜索ID,则ID = 1不应出现在结果中,因为2015年有早期服务。
编辑:谢谢所有帮助过这个的人!我接受的答案完全符合我的要求。尽管谁详细阐述了如何进一步过滤年度结果,但帕蒂对此表示赞赏。答案 0 :(得分:4)
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;
<强>附录强>
参考评论中的问题:
我如何限制它只显示那些在特定年份有服务的人?
这取决于您的具体要求,请考虑以下几点:
ID ServiceDate
--------------------
1 2014-05-01
1 2015-08-01
1 2016-07-07
2 2015-08-19
如果您指定的年份是2016年,您只想包含ID = 1,但假设您仍希望返回2014-05-01
的第一个日期,那么您需要添加带有case语句的having子句得到这个。
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;
如果你只想要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;
值得注意的是,有一个很好的理由我选择计算一年的开始,以及明年的开始和使用
WHERE o.ServiceDate >= @YearStart
AND o.ServiceDate < @YearEnd
而不仅仅是
WHERE DATEPART(YEAR, o.ServiceDate) = 2016;
在前者中,可以使用ServiceDate
上的索引,而在后者中,必须对每条记录进行DATEPART
计算,这可能会导致严重的性能问题。
ADDENDUM 2
要执行以下操作:
我想要的确切事实是在我指定的一年中最早提供服务的身份证。
然后你需要一个having子句,与我之前发布的子句不同:
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;
ADDENDUM 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;
然后,您可以将您的条件应用于视图:
SELECT *
FROM dbo.YourView
WHERE EasliestDate >= '2015-01-01'
AND EasliestDate < '2016-01-01';
答案 1 :(得分:1)
您必须在当前查询中包含WHERE:
SELECT dbo.table.ID, dbo.otherTable.ServiceDate AS EasliestDate
FROM dbo.table INNER JOIN dbo.table.ID = dbo.otherTable.ID
WHERE Month(dbo.otherTable.ServiceDate) = 1
或者您可以使用Year(dbo.otherTable.ServiceDate)= 2016进行搜索 或者您可以使用Day(dbo.otherTable.ServiceDate)= 1
或具体日期。
答案 2 :(得分:1)
使用group by和min来获取记录。否则,您可以参考http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/以获得更好的理解。
答案 3 :(得分:0)
您需要使用“分组依据”声明。试试这个:
SELECT dbo.table.ID, Max(dbo.otherTable.ServiceDate) AS LatestDate, Min(dbo.otherTable.ServiceDate as EarliestDate)
FROM dbo.table INNER JOIN dbo.table.ID = dbo.otherTable.ID
group by dbo.table.ID
答案 4 :(得分:0)
使用嵌套语句获取最小日期,然后根据ID进行匹配。
select t1.ID from table1 t1 INNER JOIN
(
SELECT ID, MIN(servicedate) MinServiceDate
FROM table2
GROUP BY ID
) t2 ON t1.ID = t2.ID