2016-03-23 24 views
0

İçinde "kullanıcı" bulunan bir Oracle tablom var ve her bir etkinliğin gerçekleştiği tarihle ilgili olarak kullanıcılarla ilgili "olaylar" içeren bir tablo var. Her kullanıcı ve en son olay gösteren basit bir tablo üretmek istiyorum, ancak ben bunu yapmak için iç içe geçmiş sorgu veya toplama işlevi oldukça çalışamıyorum, çünkü ben sütun üzerinde toplu değil İstiyorum. Basitçe MAX(event_date) istedim, bu oldukça basit olurdu, ama ben event_status where MAX(event_date) gibi bir şey istiyorum. Eminim bir prosedüre başvurmadan yapmak mümkün, ama ben tam olarak çalışamıyorum. Bir çözümü olan var mı?Oracle - Birleştirilmiş işlevi kullanarak tabloları birleştir?

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 

İstenilen sonuç:

user_name current_status 
    bob   active 
    sally  active 
    fred   on leave 

cevap

1

Bir ilişkilendirme kullanarak bu en basit olabilir d alt sorgu: Bu, bazı veritabanlarında oldukça pahalı agregasyonu (ya da eşit şekilde select distinct) sorun kaydeder

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; 

. Bunun alt sorgu için MySQL/Postgres LIMIT 1 kullandığını unutmayın. Diğer veritabanları benzer işlevlere sahiptir.

DÜZENLEME:

SQL Server 2014 ile test edilmiştir
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

Teşekkür ederim, bu beni yumrudan geçirdi. Oracle, "limit" kullanımında biraz daha gariptir - sonunda bunu ROWCOUNT = 1 gibi ROWCOUNT = 1'den ayırarak çalışmasını sağladım: u u. *, (select * (select e.status) , e.user_id = u.user_id adresinden e.event_date tarafından siparişin verildiği yer) e_event_date desc ) Burada user_recentStatus kullanıcıları u; – user1071914

0

ana fikri her kullanıcı için en son olayı seçip tabloları katılmaktır:

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 
            ) 
: Burada
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

bir sql sorgusu olduğunu
0

, YMMV diğer veritabanları

(uygun sütun ve tabloların adlarını değiştirin.)

Kısa cevap

için
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 

Uzun 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