Subquery zurückzukehren, um den neuesten Eintrag für jeden Elternteil ID

StackOverflow https://stackoverflow.com/questions/625055

  •  05-07-2019
  •  | 
  •  

Frage

Ich habe eine übergeordnete Tabelle mit Einträgen für Dokumente und ich habe eine Geschichte-Tabelle, die jedes Mal, wenn ein Benutzer greift auf eines der Dokumente einen Überwachungseintrag protokolliert.

Ich schreibe eine Suchabfrage eine Liste von Dokumenten (gefiltert nach verschiedenen Kriterien) mit der neuesten Benutzer-ID zurückzukehren jedem Dokument in der Ergebnismenge zuzugreifen.

So für


    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

Ich würde schauen, um eine Rückkehr von meiner Suche wie

bekommen

    ID | NAME       | LAST_USER_ID
    1  | Document 1 | 12345
    2  | Document 2 | 11111
    3  | Document 3 | 12345
    4  | Document 4 | 
    5  | Document 5 | 

Kann ich einfach dies mit einer SQL-Abfrage und eine Verknüpfung zwischen den beiden Tabellen?

War es hilfreich?

Lösung

revidieren, was Andy White produziert und ersetzt eckige Klammern (MS SQL Server-Notation) mit DB2 (und ISO-Standard SQL) "begrenzter Bezeichner":

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

Ich bin mir nicht ganz sicher, ob „Zeitstempel“ oder „Timestamp“ richtig ist -. Wahrscheinlich letzteres

Der Vorteil hierbei ist, dass es die innere korrelierte Unterabfrage in Andys Version mit einer einfacheren nicht-korrelierten Unterabfrage ersetzt, die das Potenzial zu sein hat (radikal?) Effizienter zu gestalten.

Andere Tipps

ich nicht den „MIT MAX (timestamp)“ erhalten könnte in SQL Server laufen - ich erfordert wie „mit max (Zeitstempel)> 2009-03-05“ einen Booleschen Ausdruck erraten habe oder etwas, das nicht in diesem Fall keine Anwendung. (Ich könnte etwas falsch sein ...)

Hier ist etwas, das scheint zu funktionieren - man beachte die Verbindung hat zwei Bedingungen (nicht sicher, ob dies gut ist oder nicht):

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
    )

Dieses verwendet keine Join, aber für einige Anfragen wie diese Ich mag die Select für den Bereich Inline. Wenn Sie die Situation fangen wollen, wenn kein Benutzer zugegriffen hat, kann man es wickelt mit einem 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>

Ich denke, es sollte wie folgt sein:

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

Dies könnte funktionieren auch:

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 )
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 */
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top