多个subselect连接到同一个表?

时间:2017-11-23 12:41:47

标签: sql postgresql

背景

我有一个Postgres数据库的节目(show_id int,标题字符串)和剧集(show_id int,ep_id int,title string,date int)。

我想发出一个查询,返回所有节目及其标题,他们的剧集数(=他们的id作为show_id的剧集数),下一集标题和下一集播出时间。时间是Unix时间戳,下一集显然是min(date) where date > now。如果节目没有即将播出的剧集,则这些字段为空。

架构示例

所示:

show_id | title
--------|-------
1       | The X-Files
2       | Fringe
3       | Seinfeld

情节:

ep_id | title             | date      | show_id
------|-------------------|-----------|---------
1     | Mulder's Holiday  | 110876621 | 1
2     | Walt Retires      | 128101332 | 2
3     | Kramer & Dracula  | 184220112 | 3
4     | Scully's Tattoo   | 100298110 | 1
5     | Skinner in Hawaii | 218101310 | 1

期望的结果集

show_title  | episode_count | next_episode      | next_airing
------------|---------------|-------------------|-----------
The X-Files | 221           | Skinner in Hawaii | 218101310
Seinfeld    | 167           | NULL              | NULL

我尝试了什么

select title, c.count, d.next_episode, d.next_airing
from shows s
inner join (select show_id, count(*)
            from episodes
            group by show_id) c
inner join (select show_id, title next_next_episode, date next_airing
            from episodes
            group by show_id) d
on c.show_id = s.show_id
on d.show_id = s.show_id

第一个内部联接可用于选择剧集计数,但复制它以选择下一集的标题和日期不会。问题似乎是,如果您选择的是聚合函数的一部分,则子选择的内连接才有效?或者类似的东西 - 我的书并没有涵盖这一点,我发现很难自己弄清楚,在谷歌度过了一半的晚上。如果有人能提供关于如何做到这一点的提示,我真的很感激。

2 个答案:

答案 0 :(得分:1)

在第二个内连接中你应该使用distiinct而不是group by ..做你没有聚合函数的事实

select s.title, c.count, d.next_episode, d.next_airing
from shows s
inner join (select show_id, count(*)
            from episodes
            group by show_id) on c.show_id = s.show_id
inner join (select distinct show_id, title next_next_episode, date next_airing
            from episodes
            ) d on d.show_id = s.show_id

我已经使用JOIN ON SQL格式安排查询..希望这不是你的db代码规则

答案 1 :(得分:1)

这有点棘手。首先,您需要一个日期过滤器。其次,如果没有下一集,你需要外连接。试试这个版本:

select s.show_id, e.episode_count, enext.title, enext.date
from shows s left join
     (select show_id, count(*) as episode_count
      from episodes e
      group by show_id
     ) e left join
     (select distinct on (ep_id) e.*
      from episodes e
      where date > extract(epoch from now())
      order by ep_id, date
     ) enext
     on enext.show_id = s.show_id;