Sql 按同一列上的多个值筛选
下面是表和任务本身的简化版本(如果需要的话) 在任何帮助中,实际的表都来自Opencart的数据库,所以我想要什么 要实现的是按制造商和属性筛选存储中的产品。我所需要的只是一个提示,说明如何在sql中实现这一点,而不一定是特定于opencart的。正在尝试学习SQL,所以请不要建议使用模块 表:Sql 按同一列上的多个值筛选,sql,attributes,opencart,conditional-statements,where,Sql,Attributes,Opencart,Conditional Statements,Where,下面是表和任务本身的简化版本(如果需要的话) 在任何帮助中,实际的表都来自Opencart的数据库,所以我想要什么 要实现的是按制造商和属性筛选存储中的产品。我所需要的只是一个提示,说明如何在sql中实现这一点,而不一定是特定于opencart的。正在尝试学习SQL,所以请不要建议使用模块 表: product ------------------- ID name description manufacturer_id 0 n0 desc0 33 1 n1 desc1
product
-------------------
ID name description manufacturer_id
0 n0 desc0 33
1 n1 desc1 56
2 n2 desc2 68
product_attribute
-------------------
pID ID text
0 12 red
0 13 xl
1 12 red
1 13 xs
2 13 xxl
SQL按制造商和属性筛选产品,条件介于
属性组(例如“颜色、大小等”)应为和,条件介于
同一组的属性(例如“颜色”)应为或。说我想得到
制造商(33或56),颜色为“红色或绿色”,尺寸为“xl或xxl”的产品:
---------------
Manufacurer
✓ 33
✓ 56
o 68
Color
✓ red
✓ green
Size
✓ xl
o xs
✓ xxl
---------------
SELECT p.ID
FROM product p
LEFT JOIN product_attribute pa ON (pa.pID = p.ID)
WHERE p.manufacturer_id = 33 OR p.manufacturer_id = 56
AND pa.text = red OR pa.text = green
AND pa.text = xl OR pa.text = xxl
应返回:
result table
--------------
ID
0
逻辑运算具有与常规数学一样的优先级
和
运算符的优先级高于或
,就像乘法优先于加法一样
另外,由于您使用的是字符串,所以不要忘记使用双引号或简单引号
p.manufacturer_id = 33 OR p.manufacturer_id = 56
AND pa.text = "red" OR pa.text = "green"
AND pa.text = "xl" OR pa.text = "xxl"
将提供与相同的结果
p.manufacturer_id = 33
OR (p.manufacturer_id = 56 AND pa.text = "red")
OR (pa.text = "green" AND pa.text = "xl")
OR pa.text = "xxl"
我想您的示例中的查询结果是
result table
--------------
ID
0
1
2
我建议你使用括号,以确保你的条件得到充分尊重
(p.manufacturer_id = 33 OR p.manufacturer_id = 56)
AND (pa.text = "red" OR pa.text = "green")
AND (pa.text = "xl" OR pa.text = "xxl")
上述查询不起作用,因为对于唯一条目,如果(pa.text=“red”或pa.text=“green”)
为true,则(pa.text=“xl”或pa.text=“xxl”)
将为false(因为pa.text值已经是“red”或“green”)
由于您需要具有红色或绿色以及xl或xxl尺寸的条目,因此您可以搜索具有两种颜色的条目我假设产品不能同时具有绿色和红色,也不能具有两种不同的尺寸
SELECT p.ID
FROM product p
LEFT JOIN product_attribute pa ON (pa.pID = p.ID)
WHERE (p.manufacturer_id = 33 OR p.manufacturer_id = 56)
AND pa.text IN ("red", "green", "xl", "xxl")
GROUP by pa.text
HAVING COUNT(*) = 2
结果
ID
--
1
因为我用MySQL测试了它,它用1开始自动递增索引
在中使用:
WHERE p.manufacturer_id IN (33, 56) AND
pa.text IN ('red', 'green') AND
pa.size IN ('xl', 'xxl')
字符串常量周围还需要单引号
编辑:
根据您的编辑,我认为您需要:
select pa.pid
from product_attribute pa join
product p
on p.id = pa.pid and p.manufacturer_id in (33, 56)
where (pa.id = 12 and pa.text in ('red', 'green')) or
(pa.id = 13 and pa.text in ('xl', 'xxl'))
group by pa.pid
having count(distinct pa.id) = 2 -- both match
我以前试过这个结构,它什么也不返回。这必须与以下事实有关:给定的x行列不能同时具有不同的值(和(pa.text=red….和(pa.text=xl
)。因此,必须采用不同的方法筛选多个值。没有pa.size
列,只有pa.text
才能使属性唯一,我使用CONCAT(pa.ID,pa.text)
所以按照你的例子,我应该使用这样的东西,其中p.manufacturer\u ID在(33,56)中,CONCAT(pa.ID,pa.text)在('12red','12green')中,CONCAT(pa.ID,pa.text)在('13xl','13xxl')中
但这也不会返回任何结果。更新后的答案似乎有效,唯一需要更改的是拥有COUNT(*)=2
到拥有COUNT(*)>1
,因为我可能拥有更多的属性组和组中更多的属性,对吗?@AlexTofan拥有COUNT(*)>1将适用于2个或更多,但它可能会提供意外的结果。最好使用HAVING COUNT(*)=MyNumberOfAttributes
@Cid在使用更多属性组进行测试后,我可以说你是对的,因此我更新了使用HAVING COUNT(*)=NumberOfAttributeGroup
,谢谢。