PostgreSQL:返回一个表中的所有行,并与另一个表中的行连接

时间:2014-02-28 09:58:15

标签: postgresql join postgresql-9.1

对于表foo中的每一行,我想用表格栏中的一行加入它。 bar中的行是与foo中名称相同的行,其最新日期早于foo中的日期。

示例:

餐鱼: 渔民与鱼类有关(例如渔民捕鱼时)

表诱饵: 渔民与诱饵有关(例如渔民试图捕鱼的东西)

它们看起来像这样:

鱼类:

 name   |      fishdate
-----------------------------
bob     | 2014-02-22 11:45:01
alice   | 2014-02-22 12:45:02
alice   | 2014-02-22 12:50:04
bob     | 2014-02-22 15:45:05
alice   | 2014-02-22 14:42:50

饵:

 name   |        date         | bait
------------------------------------
bob     | 2014-02-22 11:41:01 | worm
bob     | 2014-02-22 11:42:01 | salomon
bob     | 2014-02-22 11:47:01 | fakefish
alice   | 2014-02-22 12:40:02 | salomon
alice   | 2014-02-22 12:41:02 | worm
alice   | 2014-02-22 12:49:04 | fakefish
alice   | 2014-02-22 14:36:04 | salomon
bob     | 2014-02-22 14:40:05 | worm
alice   | 2014-02-22 14:41:04 | worm
alice   | 2014-02-22 14:42:04 | salomon
alice   | 2014-02-22 14:49:04 | fakefish

我想要的是带有鱼饵的鱼饵,目前渔民使用的鱼饵:

 name   |      fishdate       | bait
-------------------------------------
bob     | 2014-02-22 11:45:01 | salomon
alice   | 2014-02-22 12:45:02 | worm
alice   | 2014-02-22 12:50:04 | fakefish
bob     | 2014-02-22 15:45:05 | worm
alice   | 2014-02-22 14:42:50 | salomon

如何在PostgreSQL 9.1中执行此操作?

3 个答案:

答案 0 :(得分:1)

一种选择是使用相关的子查询。

实际上它会为数据中的每一行运行一条SQL语句。在这种情况下,它会从fishes中获取每个日期,并从紧接其前的baits中找到日期。

SELECT
  *
FROM
  fishes
LEFT JOIN
  baits
    ON  baits.name = fishes.name
    AND baits.date = (SELECT MAX(date)
                        FROM baits   AS lookup
                       WHERE lookup.date <= fishes.date
                         AND lookup.name  = fishes.name
                     )

答案 1 :(得分:0)

您可以使用Window functions

select name,fishdate,bait from 
(
SELECT *, rank() over (partition by fishes.name,fishes.fishdate order by baits.date desc) ranked 
from fishes inner join baits using (name) 
where fishes.fishdate>=baits.date
) A 
where ranked = 1
order by fishdate

这是SQL Fiddle

答案 2 :(得分:0)

Postgres支持window functions

select distinct
  f.name,
  fishdate,
  last_value(bait) over (partition by f.name, fishdate order by date 
    rows between current row and unbounded following) bait
from fishers f
join baits b on b.name = f.name and date <= fishdate

使用您的数据查看此SQLFiddle

即使我自己这样说,也相当优雅。