2015-02-23 25 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; 
相关问题