SQL获取字段中最后一次出现针对每一行(SQL Get Last Occurrence of Fie

2019-10-22 01:43发布

我怎么可以添加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我基本上希望它得到最大文件ID小于该行的参考该行的文档ID。

Answer 1:

你可以从“最后文件”这样的任意值:

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
;

请参阅在SQL小提琴这个工作

虽然有相同的逻辑,在一个子查询只计算列值类似的方法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
;


Answer 2:

在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;


Answer 3:

LAG可能是,如果这是一个选项,更有效。 但有使用没有特别的理由TOPMAX的伟大工程。

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


Answer 4:

有人问我有以下告诫取消删除这个......对于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>

较长线的窗函数将获取从由参考场分区和所有以前documentids为参考不包括当前文档被限制的组行的最大(documentid)。



文章来源: SQL Get Last Occurrence of Field Against Each Row