从两个表中选择

时间:2012-06-20 08:47:50

标签: sql oracle

我有2张桌子。

1. Table events: event_date, name, event
2. Table locations: loc_date, name, location

我需要从event_date之前 loc_date最后的表位置获取表事件和位置的所有行。

更新我需要为表事件中的每一行获取一个位置。例如:

events
event_date | name | event
13:53      | test1| 0
14:20      | test2| 1
18:00      | test3| 5

locations
location_date | name | location
13:20         | a    | Moscow
13:40         | b    | New-York
14:00         | c    | London
17:24         | d    | Tokio
18:00         | e    | Berlin

我想要的结果是:

event_date | name  | event | location
13:53      | test1 | 0     | New-York
14:20      | test2 | 1     | London
18:00      | test3 | 5     | Berlin

我尝试过这样的事情:

select e.*
from events e
left join locations l on l.loc_date < e.event_date

但是这个查询会返回很多行,这些行包含来自事件的相同数据和来自位置的不同数据。

2 个答案:

答案 0 :(得分:0)

这样的东西:

select e.* from events e
inner join location l on l.loc_date < e.event_date

但这不是一个好的架构,你应该有一些东西可以正确地连接两个表。

答案 1 :(得分:0)

您可以使用analytic function first_value()

select distinct e.event_date, e.name, e.event,
    first_value(l.location)
        over (partition by e.event_date, e.name, e.event
            order by l.loc_date desc) as location
from events e
left join locations l on l.loc_date < e.event_date
order by e.event_date, e.name, e.event;

EVENT NAME       EVENT LOCATION
----- ----- ---------- --------
13:53 test1          0 New-York
14:20 test2          1 London
18:00 test3          5 Tokio

请注意,test3位置是Tokio,而不是您预期结果中的柏林;那是因为您在 event_date'之前指定了'loc_date ,而柏林的loc_dateevent_date相同。如果您希望它与之匹配,则需要使用<=代替<

执行此操作的非分析方法是使用相关子查询,该子查询必须两次打到表中;我更喜欢分析方法,但这可能更容易理解:

select e.event_date, e.name, e.event, l.location
from events e
join locations l on l.loc_date = (
    select max(loc_date) from locations
    where loc_date < e.event_date
)
order by e.event_date, e.name, e.event;