2016-03-23 14 views
0

Ich habe eine Oracle-Tabelle mit "Benutzern" darin, und eine Tabelle mit "Ereignissen" bezogen auf Benutzer, Datum-gestempelt, wann jedes Ereignis stattfand. Ich würde gerne eine einfache Tabelle erstellen, die jeden Benutzer und das letzte Ereignis zeigt, das stattgefunden hat, aber ich kann die verschachtelte Abfrage- oder Aggregationsfunktion dafür nicht richtig ausarbeiten, da ich mich nicht in der Spalte zusammenfasse Ich will. Wenn ich einfach MAX(event_date) wollte, wäre das ziemlich einfach, aber ich möchte etwas wie event_status where MAX(event_date). Ich bin mir sicher, dass es möglich ist, auf eine Prozedur zu verzichten, aber ich kann es nicht ganz ausrechnen. Jeder hat eine Lösung?Oracle - Join Tabellen mit aggregierten Funktion?

user_id user_name 
    1   bob 
    2   sally 
    3   fred 



    event_id user_id event_date event_status 
    1    1  3/1/15  hired 
    2    1  3/2/15  active 
    3    3  4/1/15  hired 
    4    3  4/3/15  on leave 
    5    2  3/3/15  hired 
    6    2  4/1/15  on leave 
    7    2  5/1/15  active 

Wunschergebnis:

user_name current_status 
    bob   active 
    sally  active 
    fred   on leave 

Antwort

1

Dies kann am einfachsten mit einem Korrelat sein d Unterabfrage:

select u.*, 
     (select e.status 
     from events e 
     where e.user_id = u.user_id 
     order by e.event_date desc 
     limit 1 
     ) as Most_Recent_Status 
from users u; 

Diese Mühe Aggregat spart (oder äquivalent select distinct), die in einigen Datenbanken ziemlich teuer ist. Beachten Sie, dass dies die MySQL/Postgres LIMIT 1 für die Unterabfrage verwendet. Andere Datenbanken haben ähnliche Funktionen.

EDIT:

select u.*, 
     (select max(e.status) keep (dense_rank first order by event_date desc) 
     from events e 
     where e.user_id = u.user_id 
     ) as Most_Recent_Status 
from users u; 
+0

Danke, das hat mich über die Beule gebracht. Oracle ist etwas peinlicher bei der Verwendung von "limit" - ich habe es schließlich geschafft, indem ich ORDER BY von ROWCOUNT = 1 wie folgt trennte: wähle u. *, (wähle * aus (wähle e.status aus Ereignissen e wo e.user_id u.user_id = Sortieren nach e.event_date desc ) wobei rowcount = 1) als Most_RecentStatus von den Benutzern u; – user1071914

0

die Hauptidee ist das neueste Ereignis für jeden Benutzer auszuwählen und dann Tabellen beitreten:

select a.user_name, b.event_status 
from 
users as a 
inner join 
events as b 
on (a.user_id = b.user_id) 
inner join 
(
    select user_id, max(event_id) as event_id 
    from table2 
    group by user_id 
) as q 
on (b.user_id = q.user_id and b.event_id = q.event_id) 
0

Hier eine SQL-Abfrage:

select U.user_name, 
     E.event_status 
    from users U, 
     events E 
where U.user_id = E.user_id 
    and (E.user_id, E.event_date) = (select distinct user_id, 
              max(event_date) 
             from events 
            where user_id = E.user_id group by user_id 
            ) 
0

mit SQL Server 2014 getestet, YMMV für andere Datenbanken

(Bitte ändern Sie die Namen der Spalten und Tabellen entsprechend.)

Kurze Antwort

SELECT 
username, eventstatus 
FROM 
(
    SELECT 
     u.username, 
     e.eventstatus, 
     ROW_NUMBER() OVER (PARTITION BY u.username ORDER BY e.eventdate DESC) RowNum 
    FROM @userTable u JOIN @eventTable e ON u.userid=e.userid 
) sub 
WHERE sub.RowNum = 1 

Langer Test

DECLARE @userTable TABLE (userid INT, username VARCHAR(50)) 
DECLARE @eventTable TABLE (eventid INT, userid INT, eventdate DATETIME, eventstatus VARCHAR(20)) 

INSERT INTO @userTable VALUES (1, 'bob') 
INSERT INTO @userTable VALUES (2, 'sally') 
INSERT INTO @userTable VALUES (3, 'fred') 

INSERT INTO @eventTable VALUES (1, 1, '3/1/15', 'hired') 
INSERT INTO @eventTable VALUES (2, 1, '3/2/15', 'active') 
INSERT INTO @eventTable VALUES (3, 3, '4/1/15', 'hired') 
INSERT INTO @eventTable VALUES (4, 3, '4/3/15', 'on leave') 
INSERT INTO @eventTable VALUES (5, 2, '3/3/15', 'hired') 
INSERT INTO @eventTable VALUES (6, 2, '4/1/15', 'on leave') 
INSERT INTO @eventTable VALUES (7, 2, '5/1/15', 'active') 

SELECT 
username, eventstatus 
FROM 
(
    SELECT 
     u.username, 
     e.eventstatus, 
     ROW_NUMBER() OVER (PARTITION BY u.username ORDER BY e.eventdate DESC) RowNum 
    FROM @userTable u JOIN @eventTable e ON u.userid=e.userid 
) sub 
WHERE sub.RowNum = 1