SQL Query获取最早的日期

时间:2016-05-10 17:15:01

标签: 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

但是输出是每个ID的每个服务,其结果太多而无法排序。我希望输出只显示ID和最早的服务日期。任何建议都表示赞赏。

编辑:更确切地说,如果最早的服务日期是我指定的年份,我要查找的输出是ID和服务日期。 I.E.如果ID = 1在2015年和2016年有服务且我在2016年搜索ID,则ID = 1不应出现在结果中,因为2015年有早期服务。

编辑:谢谢所有帮助过这个的人!我接受的答案完全符合我的要求。尽管谁详细阐述了如何进一步过滤年度结果,但帕蒂对此表示赞赏。

5 个答案:

答案 0 :(得分:4)

使用GROUP BYMIN获取每个ID的第一个日期:

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 bymin来获取记录。否则,您可以参考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