3

我有一个包含文档条目的父表,并且我有一个历史表,每次用户访问其中一个文档时都会记录一个审计条目。

我正在编写一个搜索查询以返回具有最新用户 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 查询和两个表之间的连接轻松地做到这一点吗?

4

5 回答 5

4

我无法让“HAVING MAX(TIMESTAMP)”在 SQL Server 中运行 - 我想需要一个布尔表达式,如“有 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
    )
于 2009-03-09T05:29:44.693 回答
4

修改 Andy White 生成的内容,并将方括号(MS SQL Server 表示法)替换为 DB2(和 ISO 标准 SQL)“分隔标识符”:

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 版本中的内部相关子查询,这有可能(从根本上?)更有效。

于 2009-03-09T06:07:40.373 回答
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>
于 2009-03-09T05:34:20.267 回答
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 )
于 2009-03-09T05:10:09.967 回答
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 */
于 2009-03-20T20:55:33.970 回答