一次查询中的PostgreSQL条件连接和条件分离
如何创建一个查询来选择给定特征的产品,其中特征语句由“and”或“or”条件组成,取决于它们所属的组 情况描述一次查询中的PostgreSQL条件连接和条件分离,sql,postgresql,relational-division,sql-match-all,Sql,Postgresql,Relational Division,Sql Match All,如何创建一个查询来选择给定特征的产品,其中特征语句由“and”或“or”条件组成,取决于它们所属的组 情况描述 有一家商店出售各种商品 产品可能有功能,也可能没有 客户查找产品的特定功能,这意味着填写表单并发送一系列功能ID 在数据库中,每个特征仅属于一组特征 第一组(析取属性为true,称为“OR”)允许在其中一个功能与客户提交的任何功能匹配时显示产品。 示例:选择形状:圆形、正方形、三角形显示圆形、正方形或三角形的产品 第二组(析取属性为false,称为“AND”)仅当产品具有客户提交的所有
示例:选择形状:圆形、正方形、三角形显示圆形、正方形或三角形的产品
示例:选择颜色:红色、绿色、蓝色显示红色、绿色和蓝色的产品
除了那些没有功能的产品外,它还能工作
SELECT product_id
FROM product_features
WHERE product_features.feature_id IN (
SELECT feature_id FROM features
LEFT JOIN feature_groups
ON features.feature_group_id = feature_groups.feature_group_id
WHERE feature_id IN (11, 12, 13) AND feature_groups.disjunction = TRUE
)
GROUP BY product_id
“和”查询无法使用此查询,因为析取为false的要素数量未知
SELECT product_id FROM product_features
WHERE feature_id IN (43, 53, 63)
GROUP BY product_id
HAVING COUNT(DISTINCT feature_id) = 3
“或”案例
更简单、更快:
SELECT DISTINCT pf.product_id
FROM product_features pf
LEFT JOIN features f USING (feature_id)
LEFT JOIN feature_groups fg USING (feature_group_id)
WHERE (f.feature_id = ANY (_my_arr)
AND fg.disjunction)
OR _my_arr = '{}';
。。。其中\u my_arr
可以是'{11,12,13}'::int[]
或'{}'::int[]
。如果\u我的arr
将为NULL
请使用\u我的arr为NULL
- 由于
在和
之前绑定,因此不需要括号。不过,它们可能会提高可读性或
或DISTINCT
。。这两种都很好分组依据
。。由于这是一种布尔类型,因此可以缩短语法和fg.析取
- 联接通常比子句中的另一个
更快
只是一种与您的(有用的!)命名约定配合使用的符号快捷方式使用
SELECT product_id
FROM products p
WHERE EXISTS (
SELECT 1
FROM product_features pf
JOIN features f USING (feature_id)
JOIN feature_groups fg USING (feature_group_id)
WHERE pf.product_id = p.product_id
AND f.feature_id = ANY (_my_arr)
AND fg.disjunction
)
OR _my_arr = '{}';
我宁愿在你的应用程序中根据输入(有功能/无功能)拆分案例。与第二种形式无关
“和”案例
这是关系划分的经典案例。我们已经收集了一整套查询技术来处理这个相关问题:可以是:
SELECT product_id
FROM product_features p1
JOIN product_features p2 USING (product_id)
JOIN product_features p3 USING (product_id)
...
WHERE p1.feature_id = 43
AND p2.feature_id = 53
AND p3.feature_id = 63
...
我忽略了示例中的非特征组。析取
,因为它也不在问题中。如果需要,请添加它。在生成查询之前,我会选择有效的功能\u id
“除了那些没有功能的产品外,它也可以工作。”-如果它们没有功能,不应该通过“或”查询将其删除吗?根据您的描述,“没有功能的产品”将永远不会出现在您的任何一个用例中。@PinnyM我应该使用不同的表达式,并更好地描述它。当客户选择至少一个特征时,查询工作正常。那么“或”查询确实应该消除没有特性的产品。但是,如果客户没有选择任何功能并查找产品,则应显示所有产品。在这种情况下,使用“或”查询不能按需要工作。请记住,WHERE in子句中设置的功能ID不仅是“disjunction is true”类型,查询会动态过滤它们,因此可能无法使用这些ID。我的印象是,我没有足够清楚地表达自己。您的“或”查询看起来比我的好得多,我非常感谢您的提示,但它仍然不能按需要工作。WHERE IN子句包含客户选择的一组功能ID。如果这些功能都不属于具有“disjunction is true”属性的组,或者客户没有选择任何功能,则查询不返回产品,但在这种情况下,它应该返回所有产品。完美”,或者“查询完成任务”。“和”查询似乎非常快,但维护起来有点困难,特别是如果有数百个功能的话。此外,混合特征id集在一个数组中一起发送,因此不知道哪个特征id属于“或”或“和”查询。在本例中,这些属于“析取为假”组的特征必须以某种方式加以选择。@rafis:我在回答你的问题,我可能会补充一些细节。应该引起公众的兴趣。我不是做你所有的工作。如果你遇到了另一个障碍,打开一个新问题,清楚地定义一个问题。