2016-05-10 147 views
1

我是SQL新手,並且有一個包含ID和服務日期的大型數據庫,我需要編寫一個查詢來爲每個ID提供服務的第一個日期。SQL查詢獲取最早日期

我想:

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

一般而言,您並不需要限制'from'子句中的表名。所以你真的應該在其他地方擺脫'dbo.'。 – shawnt00

+0

@ shawnt00 Microsoft SQL Server管理Studio正在自動添加dbo。部分每當我使用表名。 – CSjunkie

+0

我想這並不讓我感到意外,但它並不是最好的形式。您可以考慮查看別名(又名相關名稱)。 – shawnt00

回答

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; 

附錄

在談到一個問題的意見:

如何我是否也會限制它只顯示那些哈d特定年份的服務?

這要看您的具體要求,請考慮以下設置:

ID  ServiceDate 
-------------------- 
1  2014-05-01 
1  2015-08-01 
1  2016-07-07 
2  2015-08-19 

你只希望包括ID = 1,如果你指定的一年是2016年,但假設你還是想回去​​的第一個日期,那麼你需要添加一個具有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年的一個最早的日期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計算,這可能會導致嚴重的性能問題。

附錄2

要做到以下幾點:

我想那麼會是誰的ID最早的服務是我指定的年度確切的事情。

那麼你就需要一個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; 

增編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'; 
+0

太棒了!這很好。雖然這不是我的問題,但我怎樣才能限制它只顯示那些在特定年份有服務的人?我會在組之前添加「WHERE dbo.otherTable.serviceDate> = YYYY - MM - DD和 CSjunkie

+0

@CSJunkie最早的服務日期可能會在當年之外,或者您只對特定年份的服務感興趣? – shawnt00

+0

@ shawnt00我試圖找出每個ID何時輸入到我的系統中,但由於該信息並非總是通過數據輸入記錄,所以我使用最早的服務日期作爲估計值。帕蒂展示瞭如何過濾下面的這些信息。感謝您的詢問:) – CSjunkie

0

您需要使用「Group by」語句。試試這個: 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

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 

或者你可以用年份搜索(dbo.otherTable.ServiceDate)= 2016 或者你可以用日(DBO .otherTable.ServiceDate)= 1

或特定的日期。

+0

或者您可以使用」Order by「語句。 – Patty

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