SQL 获取每行最后一次出现的字段
SQL Get Last Occurrence of Field Against Each Row
如何像这样添加 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 |
+------------+-----------+----------------+
table 可能是随机顺序,但在最后一个文档 ID 中,我基本上希望它获得小于该行引用的该行文档 ID 的最大文档 ID。
在 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;
我被要求取消删除,但有以下警告...对于 SQL 大于 2008 的服务器版本:
您可以使用 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>
那条较长的行是 window 函数将从由您的引用字段分区的行组中获取 max(documentid),并受该引用的所有先前文档 ID 的限制,不包括当前文档。
您可以通过这种方式从 "last document" 中获取任何值:
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一列:
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
;
如果可以的话,LAG
可能会更有效率。但是当 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;
如何像这样添加 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 |
+------------+-----------+----------------+
table 可能是随机顺序,但在最后一个文档 ID 中,我基本上希望它获得小于该行引用的该行文档 ID 的最大文档 ID。
在 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;
我被要求取消删除,但有以下警告...对于 SQL 大于 2008 的服务器版本:
您可以使用 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>
那条较长的行是 window 函数将从由您的引用字段分区的行组中获取 max(documentid),并受该引用的所有先前文档 ID 的限制,不包括当前文档。
您可以通过这种方式从 "last document" 中获取任何值:
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一列:
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
;
LAG
可能会更有效率。但是当 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;