我正在尝试查询文档的最新状态,但没有取得任何成功。我用于查询的表格为docs
,docStats
和statusList
。
docs
表:
| docId | docTitle | venIdFk |
+-------+------------+---------+
| 1 | Contract 1 | 81 |
| 2 | Contract 2 | 37 |
+-------+------------+---------+
docStats
表:
| docStatIdPk | docStat | docStatDt | docIdFk |
+-------------+---------+-------------------------+---------+
| 7 | 1 | 2016-09-16 09:00:00.000 | 1 |
| 10 | 2 | 2016-09-16 09:30:00.000 | 1 |
| 11 | 4 | 2016-09-17 08:30:00.000 | 1 |
| 12 | 1 | 2016-09-17 10:00:00.000 | 2 |
+-------------+---------+-------------------------+---------+
statusList
表:
| statId | stat |
+--------+--------------+
| 1 | Needs Review |
| 2 | In Review |
| 3 | Denied |
| 4 | Accepted |
+--------+--------------+
使用以下内容,我可以在docs表中获取文档的最新状态:
SELECT
d2.docId, MAX(ds2.docStatDt) AS maxStatDt
FROM
docs d2
INNER JOIN
docStats ds2 ON d2.docId = ds2.docIdFk
GROUP BY
d2.docId
结果是正确的:
| docId | maxStatDt |
+-------+-------------------------+
| 1 | 2016-09-17 08:30:00.000 |
| 2 | 2016-09-17 10:00:00.000 |
+-------+-------------------------+
但是我需要在查询中添加其他列,这就是它中断的地方。它添加了docId 1的所有记录,因为' stat'包含在SELECT中,docId 1有多种状态。如何编写此查询以便它只返回docId 1的最新状态?
以下是我现在拥有的查询:
SELECT
d.docid, d.doctitle, d.doctype, d.docorg, d.docdept,
s.stat,
mdt.maxdate AS crntDocStatDtSet
FROM
docs d
INNER JOIN
docstats ds ON d.docid = ds.docidfk
INNER JOIN
statuslist s ON ds.docstat = s.statid
INNER JOIN
(SELECT
d2.docid, Max(ds2.docstatdt) AS MaxDate
FROM
docs d2
INNER JOIN
docstats ds2 ON d2.docid = ds2.docidfk
GROUP BY
d2.docid) mdt ON d.docid = mdt.docid
WHERE
d.docid = '1'
GROUP BY
d.docid, d.doctitle, d.doctype, d.docorg, d.docdept,
s.stat, mdt.maxdate
结果如下:
| docId | docTitle | docType | docOrg | docDept | stat | crntDocStatDtSet |
+-------+------------+---------+--------+---------+--------------+-------------------------+
| 1 | Contract 1 | 3 | 3 | 2 | Accepted | 2016-09-17 08:30:00.000 |
| 1 | Contract 1 | 3 | 3 | 2 | In Review | 2016-09-17 08:30:00.000 |
| 1 | Contract 1 | 3 | 3 | 2 | Needs Review | 2016-09-17 08:30:00.000 |
+-------+------------+---------+--------+---------+--------------+-------------------------+
答案 0 :(得分:3)
;WITH cte AS (
SELECT
d.docId,
d.docTitle,
d.doctype,
d.docOrg,
d.docDept,
s.stat,
ROW_NUMBER() OVER (PARTITION BY d.docId ORDER BY ds.docStatDt DESC) as RowNumber
FROM
docs d
INNER JOIN docStats ds
ON d.docId = ds.docIdFk
INNER JOIN statusList s
ON ds.docStat = s.statId
)
SELECT *
FROM
cte
WHERE
RowNumber = 1
最好使用分区的ROW_NUMBER()。 MAX()你使用它的方式最终会得到1个以上的结果。如果它们相等则需要多于1个,那么只需使用DENSE_RANK()代替ROW_NUMBER()所在的位置。
您要前往的路线也是一种有效的方法,但您的加入的ON条件没有ON ds.docStatDt = mdt.MaxDate,这意味着您实际上并未将结果限制为最后一条记录。添加该条件可能会给你你想要的东西。
SELECT
d.docId,
d.docTitle,
d.doctype,
d.docOrg,
d.docDept,
s.stat,
mdt.MaxDate AS crntDocStatDtSet
FROM
docs d
INNER JOIN docStats ds
on d.docId = ds.docIdFk
INNER JOIN statusList s
ON ds.docStat = s.statId
INNER JOIN (
SELECT d2.docId, MAX(ds2.docStatDt) as MaxDate
FROM docs d2
INNER JOIN docStats ds2
ON d2.docId = ds2.docIdFk
GROUP BY d2.docId
) mdt
ON d.docId = mdt.docId
AND ds.docStatDt = mdt.MaxDate
WHERE d.docId = '1'
GROUP BY
d.docId,
d.docTitle,
d.doctype,
d.docOrg,
d.docDept,
s.stat,
mdt.MaxDate
答案 1 :(得分:1)
一种非常有效的方法是使用outer apply
:
select d.*, ds.*
from docs d outer apply
(select top 1 ds.*
from docstats ds
where ds.docIdFk = d.docId
order by docStatDt desc
) ds;
当然,您也可以加入状态字符串,但这似乎不是您问题的要点。