Oracle - 使用聚合函数连接表?

时间:2016-03-23 20:27:10

标签: sql oracle

我有一个带有“users”的Oracle表,以及一个包含与用户相关的“事件”的表,并在每个事件发生时加盖日期戳。我想制作一个简单的表格,显示每个用户和发生的最新事件,但我无法完成嵌套查询或聚合功能,因为我是没有聚合我想要的列。如果我只是希望MAX(event_date)相当简单,但我想要event_status where MAX(event_date)之类的东西。我敢肯定,如果不诉诸程序就可以做到,但我无法解决这个问题。有人有解决方案吗?

    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

期望的结果:

    user_name   current_status
    bob          active
    sally        active
    fred         on leave

4 个答案:

答案 0 :(得分:1)

使用相关子查询可能最简单:

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;

这节省了聚合(或等效select distinct)的麻烦,这在某些数据库中相当昂贵。请注意,这使用MySQL / Postgres LIMIT 1作为子查询。其他数据库具有类似的功能。

编辑:

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;

答案 1 :(得分:0)

主要思想是为每个用户选择最新事件,然后连接表:

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)

答案 2 :(得分:0)

这是一个SQL查询:

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
                                    )

答案 3 :(得分:0)

使用SQL Server 2014测试,YMMV测试其他数据库

(请适当更改列和表的名称。)

简短回答

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

长时间测试

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