如何简化此PostgreSQL查询(按联接表过滤)

如何简化此PostgreSQL查询(按联接表过滤),sql,postgresql,Sql,Postgresql,比如说我和一个角色(有很多)电影的关系 我想通过角色名和电影标题过滤我的结果。所以我想返回所有名字像“Sam”的角色,并且该角色必须至少出现在一部电影中,电影标题像“Sam the movie”我仍然希望所有电影也与角色相关 我只是想知道有没有更好的方法?有可能在一个查询中得到它吗 WITH t1 AS (SELECT c.id, c.name, array_agg(m.title) AS movie_titles FROM characters c LEFT JOIN characters_

比如说我和一个角色(有很多)电影的关系

我想通过角色名和电影标题过滤我的结果。所以我想返回所有名字像“Sam”的角色,并且该角色必须至少出现在一部电影中,电影标题像“Sam the movie”我仍然希望所有电影也与角色相关

我只是想知道有没有更好的方法?有可能在一个查询中得到它吗

WITH t1 AS 
(SELECT c.id, c.name, array_agg(m.title) AS movie_titles FROM characters c
LEFT JOIN characters_movies cm ON cm.character_id = c.id
LEFT JOIN movies m ON m.id = cm.movie_id
WHERE c.name LIKE '%Sam%'
GROUP BY c.id)

SELECT * FROM t1 WHERE exists 
(SELECT * FROM unnest(movie_titles) AS title
WHERE name LIKE '%Sam the Movie%')

在一个查询中,它是这样的(没有ddl就无法测试)。请注意,我是如何使用不同的别名两次加入电影的。与
m
的连接确保标题上有匹配项。第二个
am
是获取所有标题。我很确定,不需要使用
左连接
来获得您想要的结果,因此我使用了正常的
连接
,这往往更有效

SELECT c.id, c.name, array_agg(am.title) AS movie_titles 
  FROM characters c
    JOIN characters_movies cm ON cm.character_id = c.id
    JOIN movies m ON (m.id = cm.movie_id AND m.name LIKE '%Sam the Movie%')
    JOIN characters_movies acm ON acm.character_id = c.id
    JOIN movies am ON (am.id = acm.movie_id)
WHERE c.name LIKE '%Sam%'
GROUP BY c.id

这个查询为我过滤掉电影,这是我以前遇到的问题(获得正确的角色,但它会删除所有与名称不匹配的电影)。不过,我确实通过使用您的查询找到了解决方案。在
WHERE
子句中添加了
,然后检查字符id是否在同一查询中。不确定这是否比以前更好,因为我从同一个表中选择了两次。@cdv,我忽略了我还需要加入
characters\u movies
两次,我已经在我的答案中更新了查询。现在可以工作了。从来没有想过要在连接表上加入两次。谢谢