Dim*_*ets 2 postgresql relational-division
我在stackoverlow上问过同样的问题,但没有得到答案,所以这就是我在这里问的原因(我读过应该在 SO 上问简单的 sql 问题,但我别无选择)。
假设我有 3 个表:posts
,post_categories
和categories
. 我正在实现某种带有过滤器的页面,我可以在其中按类别过滤帖子。用户可以选择多个类别。当他选择多个时,它们应该相加。我无法让它工作。我现在拥有的是简单的IN()
SQL 子句:
SELECT posts.id, post_categories.category_id FROM posts
JOIN post_categories ON posts.id = post_categories.post_id
WHERE post_categories.category_id IN (1,2,3) LIMIT 10;
Run Code Online (Sandbox Code Playgroud)
但它并不匹配所有的 id,它是OR
,我需要AND
. 我在这里需要的是查找类别为 的所有帖子id=1 AND id=2 AND id=3
,但此查询返回IN()
列表中至少有一个类别的帖子。
IN
就像写作= ANY
,例如
regress=> SELECT 1 = ANY (ARRAY[1, 2, 3]);
?column?
----------
t
(1 row)
Run Code Online (Sandbox Code Playgroud)
对您的问题的简单解释是说您要求的是= ALL
,但这很少有意义:
regress=> SELECT 1 = ALL (ARRAY[1, 2, 3]);
?column?
----------
f
(1 row)
Run Code Online (Sandbox Code Playgroud)
你有什么真正想要的是找到所有posts
有相应post_categories
的每一家上市集的条目category_id
。
与关系数据库中的惯例一样,只要您清楚地构建了问题,解决方案就会开始自行编写。
您可以执行多重连接,就像 Daniel 建议的那样,但这很痛苦,因为它需要动态 SQL。或者您可以使用关系集操作。
相反,我可能会使用 PostgreSQL 的数组功能。如果您提供了示例数据,这会更容易,但我认为您需要类似以下内容,它会找到与帖子匹配的每个类别,然后检查所有类别是否匹配(HAVING
子句):
SELECT
posts.id
FROM posts
INNER JOIN post_categories ON posts.id = post_categories.post_id
WHERE post_categories.category_id IN (1,2,3)
GROUP BY posts.id
HAVING array_agg(post_categories.category_id) @> ARRAY[1,2,3]
LIMIT 10
Run Code Online (Sandbox Code Playgroud)
未经测试,因为您没有以CREATE TABLE
和INSERT
s 形式提供示例数据,但这是总体思路。@>
表示“数组包含”;我怀疑它会比使用array_agg(category_id ORDER BY category_id)
和对排序ARRAY
文字进行相等测试更有效,因为您避免了聚合排序。
您可以省略该WHERE
子句,这仍然有效,但它可能会很慢,因为它无法过滤掉在进行聚合之前没有任何类别匹配的帖子。
顺便说一句,LIMIT
没有ORDER BY
通常是一个错误。数据库可以按任何顺序返回任何一组 10 个匹配结果。
归档时间: |
|
查看次数: |
218 次 |
最近记录: |