2015-02-23 57 views
1

我如何可以添加LastDocumentID列像這樣:SQL獲取字段中最後一次出現針對每一行

+------------+-----------+----------------+ 
| DocumentID | Reference | LastDocumentID | 
+------------+-----------+----------------+ 
|   1 | A   | NULL   | 
|   2 | A   | 1    | 
|   3 | A   | 2    | 
|   4 | B   | NULL   | 
|   5 | B   | 4    | 
|   6 | C   | NULL   | 
|   7 | C   | 6    | 
|   8 | C   | 7    | 
|   9 | C   | 8    | 
+------------+-----------+----------------+ 

表可以在一個隨機的順序,但在最後一個文檔ID我基本上是想讓它變得最大文檔ID小於該行的參考文檔的文檔ID。

+0

你試過了什麼? – 2015-02-23 20:55:26

回答

0

你可以從「最後文件」這樣的任意值:

SELECT 
    D.DocumentID, 
    D.Reference, 
    LastDocumentID = R.DocumentID 
FROM 
    dbo.Documents D 
    OUTER APPLY (
     SELECT TOP 1 * 
     FROM dbo.Documents R 
     WHERE 
     D.Reference = R.Reference 
     AND R.DocumentID < D.DocumentID 
     ORDER BY R.DocumentID DESC 
    ) R 
; 

See this working in a SQL Fiddle

雖然具有相同的邏輯,在一個子查詢WHERE子句中計算剛剛列值類似的方法,這允許您從以前的文檔中拉出多個列,並演示OUTER APPLY。如果您想要等效的INNER連接(不包括之前沒有的行),請更改爲CROSS APPLY

僅供參考,以下是實現此目的的單值方法。你基本上把包含在OUTER APPLY到括號中的查詢,並且只選擇一列:

SELECT 
    D.DocumentID, 
    D.Reference, 
    LastDocumentID = (
     SELECT TOP 1 R.DocumentID 
     FROM dbo.Documents R 
     WHERE 
     D.Reference = R.Reference 
     AND R.DocumentID < D.DocumentID 
     ORDER BY R.DocumentID DESC 
    ) 
FROM 
    dbo.Documents D 
; 

或者,您也可以只使用Max

SELECT 
    D.DocumentID, 
    D.Reference, 
    LastDocumentID = (
     SELECT Max(R.DocumentID) 
     FROM dbo.Documents R 
     WHERE 
     D.Reference = R.Reference 
     AND R.DocumentID < D.DocumentID 
    ) 
FROM 
    dbo.Documents D 
; 

如果你使用SQL Server 2012及以上,你可以用它的更高級的語法來實現窗口化功能:

SELECT 
    D.DocumentID, 
    D.Reference, 
    LastDocumentID = Max(D.DocumentID) OVER (
     PARTITION BY D.Reference 
     ORDER BY D.DocumentID ASC 
     ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING 
    ) 
FROM 
    dbo.Documents D 
; 
1

在SQL Server 2012+中,您可以使用lag()。在SQL Server 2008中,您可以使用相關子查詢或外部應用。這裏有一個方法:

select documentid, reference, 
     (select top 1 documentid 
     from table t2 
     where t2.reference = t.reference and 
       t2.documentid < t.documentid 
     order by documentid desc 
     ) as LastDocumentId 
from table t; 
+0

您不在子查詢內進行排序。 – shawnt00 2015-02-23 21:16:27

+0

@ shawnt00。 。 。謝謝。 – 2015-02-23 21:18:49

+0

我認爲這也可以使用'MAX(documentid)'而不是'top 1 documentid'來完成,而忽略'order by'子句。 – Turophile 2015-02-23 21:35:15

0

有人問我有以下告誡取消刪除這個......對於SQL Server版本比2008年更大:

您可以用窗口函數完成這個

SELECT 
    DocumentID, 
    Reference, 
    MAX(DocumentID) OVER (PARTITION BY Reference ORDER BY DocumentID ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS LastDocumentID 
FROM 
    <table> 

窗口函數較長的行將從您的引用字段分隔的行組中獲取最大值(documentid),並受所有以前的文檔限制,該引用不包括當前文檔。

+0

SQL Server 2008不支持窗口函數,但不支持'ROWS'子句。 – ErikE 2015-02-23 21:05:47

0

LAG可能是m如果這是一個選擇,礦石高效。但當MAX工作良好時,沒有特別的理由使用TOP

select 
    documentid, reference, 
    (
     select max(documentid) from table as t2 
     where t2.reference = t1.reference and t2.documentid < t1.documentid 
    ) 
from table as t1; 
相關問題