【问题标题】:Is RIGHT JOIN the way to go with this query?RIGHT JOIN 是使用此查询的方式吗?
【发布时间】:2018-12-17 17:00:26
【问题描述】:

我在 PostgreSQL 9.2.24 数据库中有表:

CREATE TABLE episodes_list (
  mid      serial PRIMARY KEY  -- movie id
, title    text NOT NULL
, is_movie integer NOT NULL    -- 1 for movie, 0 for episode
);

我需要在剧集的左侧标题和所有电影(即使没有剧集的电影)的右侧标题上显示。

103 | Microcosmos (high quality)                    |        1
103 | Snails' sexual act                            |        0
103 | Landing                                       |        0

这里有一些记录。所以例如。 'Microcosmos'应该在右边两次,蜗牛的性行为和着陆在左边。应该是这样的:

 Landing                                       | Microcosmos (high quality)
 Snails' sexual act                            | Microcosmos (high quality)

我是这样写的:

select e1.title, e2.title from episodes_list e1 right join episodes_list e2 on e1.is_movie = 0 and e2.is_movie = 1 and e1.mid = e2.mid;

但它仍然显示在剧集的正确标题上,而不是只显示在电影标题上(所以我得到了我不应该得到的额外台词)。所以它看起来像这样: 但它看起来像这样:

 Landing                                       | Microcosmos (high quality)
 Snails' sexual act                            | Microcosmos (high quality)
                                               | Snails' sexual act

我在这里做错了什么以及查询应该是什么样子?

【问题讨论】:

  • 那太老了,现在不受支持。 Urgently consider upgrading to a current version.
  • 我受伤了,但这是我大学的任务,我坚持使用这个版本
  • 对你的大学来说不是很讨人喜欢,但对这个查询没有任何影响。
  • 我继续添加了一个基于猜测的表定义。如有不妥请edit
  • is_movie integer NOT NULL 转换为episode_type_id 并添加一个表episode_type 可能更有意义,其中存储类型moviesepisode 这样您可以更轻松地添加@ 987654333@以后输入例如。

标签: sql postgresql join


【解决方案1】:

这可能是您的查询:

SELECT epi.title AS episode, mov.title AS movie
FROM        episodes_list epi
RIGHT  JOIN episodes_list mov ON epi.is_movie = 0
                             AND mov.mid = epi.mid
WHERE  mov.is_movie = 1;

这会将所有部电影返回到右侧,并在可用的情况下将剧集扩展到左侧。

is_movie 实际上应该是一个 boolean 标志。 integer 不是正确的类型。

最重要的一点是:格式化查询(以任何一致的方式,不一定像我的那样)并在事情变得复杂时使用描述性别名。

您遇到的逻辑问题:WHERE 子句中的条件等价于INNER JOIN 子句中的条件,但OUTER JOIN 中的条件相同。(LEFT JOIN / @ 987654331@ 是 LEFT OUTER JOIN / RIGHT OUTER JOIN 的缩写。)
见:

【讨论】:

    【解决方案2】:

    您需要在选择剧集记录的表上使用自 LEFT JOIN,并使用仅过滤电影的 WHERE 子句。

    下面的查询应该可以完成工作:

    select 
        e2.title, 
        e1.title 
    from episodes_list e1 
    left join episodes_list e2 
        on e2.is_movie = 0
        and e1.mid = e2.mid
    where e1.is_movie = 1
    

    e1 代表电影记录。 e2 代表情节记录。左连接允许考虑没有剧集的电影。

    【讨论】:

    • 效果很好,但为什么'on e1.is_movie = 1' 不能过滤掉这些记录,而我必须添加'where e1.is_movie = 1'?
    • LEFT JOIN 是一个可选的连接,这意味着即使没有剧集,查询仍然会返回电影。您不希望过滤电影的条件是可选的,您需要它是强制性的。否则,您最终会在第一列中显示剧集(第二列为空)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 2015-08-25
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多