SQL获取每行的字段的最后一次出现

时间:2015-02-23 20:53:11

标签: sql sql-server-2008

如何添加LastDocumentID列,如下所示:

+------------+-----------+----------------+
| 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中,我基本上希望它获得的Max Document ID小于该行的文档ID,该行的参考文献ID <。 / p>

4 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

对于大于2008的SQL Server版本,我被要求取消删除以下警告...

您可以使用Window函数

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

该较长的行是窗口函数将从由引用字段分区的行组中获取max(documentid),并受该引用的所有先前文档的限制,不包括当前文档。

答案 2 :(得分: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。如果您想要等效的CROSS APPLY联接(不包括之前没有的行),请更改为INNER

作为参考,这是执行此操作的单值方法。您基本上将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
;

答案 3 :(得分:0)

如果这是一个选项,

LAG可能会更有效率。但是当TOP效果很好时,没有特别的理由使用MAX

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