我有一个包含文档条目的父表,我有一个历史表,每次用户访问其中一个文档时都会记录一个审计条目。
我正在编写一个搜索查询,以返回一个文档列表(按各种条件筛选),并使用最新的用户ID访问结果集中返回的每个文档。
因此
DOCUMENTS
ID | NAME
1 | Document 1
2 | Document 2
3 | Document 3
4 | Document 4
5 | Document 5
HISTORY
DOC_ID | USER_ID | TIMESTAMP
1 | 12345 | TODAY
1 | 11111 | IN THE PAST
1 | 11111 | IN THE PAST
1 | 12345 | IN THE PAST
2 | 11111 | TODAY
2 | 12345 | IN THE PAST
3 | 12345 | IN THE PAST
我希望从我的搜索中获得回报,如
ID | NAME | LAST_USER_ID
1 | Document 1 | 12345
2 | Document 2 | 11111
3 | Document 3 | 12345
4 | Document 4 |
5 | Document 5 |
我可以使用一个SQL查询和两个表之间的连接轻松完成此操作吗?
答案 0 :(得分:4)
我无法在SQL Server中运行“HAVING MAX(TIMESTAMP)” - 我想需要一个布尔表达式,例如“有max(TIMESTAMP)> 2009-03-05”或其他东西,它不会在这种情况下适用。 (我可能做错了......)
这里似乎有用 - 注意连接有2个条件(不确定这是否好):
select
d.ID,
d.NAME,
h."USER_ID" as "LAST_USER_ID"
from Documents d
left join History h
on d.ID = h.DOC_ID
and h."TIMESTAMP" =
(
select max("TIMESTAMP")
from "HISTORY"
where "DOC_ID" = d.ID
)
答案 1 :(得分:4)
修改Andy White生成的内容,并用DB2(和ISO标准SQL)替换方括号(MS SQL Server表示法)“分隔标识符”:
SELECT d.id, d.name, h.last_user_id
FROM Documents d LEFT JOIN
(SELECT r.doc_id AS id, user_id AS last_user_id
FROM History r JOIN
(SELECT doc_id, MAX("timestamp") AS "timestamp"
FROM History
GROUP BY doc_id
) AS l
ON r."timestamp" = l."timestamp"
AND r.doc_id = l.doc_id
) AS h
ON d.id = h.id
我不能确定“timestamp”或“TIMESTAMP”是否正确 - 可能是后者。
这样做的好处是它用一个更简单的非相关子查询替换了Andy版本中的内部相关子查询,该查询有可能(从根本上)更有效。
答案 2 :(得分:3)
这不使用连接,但对于像这样的一些查询,我想内联选择字段。如果你想在没有用户访问的情况下捕获这种情况,你可以用NVL()包装它。
select a.ID, a.NAME,
(select x.user_id
from HISTORY x
where x.doc_id = a.id
and x.timestamp = (select max(x1.timestamp)
from HISTORY x1
where x1.doc_id = x.doc_id)) as LAST_USER_ID
from DOCUMENTS a
where <your criteria here>
答案 3 :(得分:1)
我认为它应该是这样的:
SELECT ID, Name, b.USER_ID as LAST_USER_ID
FROM DOCUMENTS a LEFT JOIN
( SELECT DOC_ID, USER_ID
FROM HISTORY
GROUP BY DOC_ID, USER_ID
HAVING MAX( TIMESTAMP )) as b
ON a.ID = b.DOC_ID
这也可能有效:
SELECT ID, Name, b.USER_ID as LAST_USER_ID
FROM DOCUMENTS a
LEFT JOIN HISTORY b ON a.ID = b.DOC_ID
GROUP BY DOC_ID, USER_ID
HAVING MAX( TIMESTAMP )
答案 4 :(得分:0)
Select ID, Name, User_ID
From Documents Left Outer Join
History a on ID = DOC_ID
Where ( TimeStamp = ( Select Max(TimeStamp)
From History b
Where a.DOC_ID = b.DOC_ID ) OR
TimeStamp Is NULL ) /* this accomodates the Left */