3

ドキュメントのエントリを持つ親テーブルがあり、ユーザーがドキュメントの 1 つにアクセスするたびに監査エントリを記録する履歴テーブルがあります。

結果セットで返される各ドキュメントにアクセスするための最新のユーザー 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 | 

1 つの SQL クエリと 2 つのテーブル間の結合でこれを簡単に実行できますか?

4

5 に答える 5

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 に答える
4

「HAVING MAX(TIMESTAMP)」を SQL Server で実行することができませんでした - 「having 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 に答える
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 に答える