如何从MySQL表中选择按一列分组的行,并在另一列中选择所需的值
我需要筛选某些属性存储在符合所有必需属性的联接表中的产品,即用户需要能够通过添加需求逐步缩小搜索范围 考虑到以下简化的产品属性表,问题实际上只涉及属性表,而不是连接: id product_id property value --------------------------------- 1 1 color red 2 1 size small 3 2 color red 4 2 size large 这是可行的,但我担心性能,似乎有更好的方法 最终,这将需要与products表连接,或至少用于过滤products表: id name ------------- 1 Product 1 2 Product 2 我忘了提到,我有两个属性表连接到我需要筛选的产品,一个具有产品的常规属性,另一个具有类似变体的可用可配置选项。 该场景允许用户过滤以下产品: 显示性别为“男性”、品牌为“nike”和尺码为“小型”的产品,其中性别和品牌为“属性”,尺码在添加到购物车时可在选项中配置 使用带有计数的组的解决方案仍然适用于两个联接的表,但会变得混乱,所需的组计数是第一个表上所需选项的数量乘以第二个表上的数量如何从MySQL表中选择按一列分组的行,并在另一列中选择所需的值,sql,mysql,database,Sql,Mysql,Database,我需要筛选某些属性存储在符合所有必需属性的联接表中的产品,即用户需要能够通过添加需求逐步缩小搜索范围 考虑到以下简化的产品属性表,问题实际上只涉及属性表,而不是连接: id product_id property value --------------------------------- 1 1 color red 2 1 size small 3 2 color red 4 2
我可以只从属性和另一个表中获取id,然后只做一个select where id INID,为两个属性表匹配一组id,但我不喜欢使用非常长的id列表来执行此操作。不确定这是否更快,但是从您的筛选条件生成的子查询中进行连接可以工作:
Select p.name, p.id from product p,
(select product_id from properties where value='red') colors,
(select product_id from properties where value='small') sizes
where p.id=colors.product_id and p.id=sizes.product_id
您可以将表连接到自身:
SELECT
prop1.product_id
FROM
properties prop1
JOIN properties prop2
ON prop1.product_id = prop2.product_id
WHERE
prop1.property = 'color' and prop1.value = 'red'
and prop2.property = 'size' and prop2.value = 'small'
属性值数据模型的另一个陷阱 假设您想要颜色匹配红色、大小匹配小尺寸的产品,您在问题中不会说属性实际上很重要,只是值,问题的很大一部分是,您如何表示所需匹配的列表?它们是否会作为分隔字符串传递、存储在临时表中、动态构建的SQL或其他内容 如果可以将它们临时或以其他方式放入表中,那么以下查询应该可以工作。由于子查询的存在,性能将非常依赖于您正在处理的数据量及其索引方式。此外,如果同一产品的表中有重复的属性,那么它可能会出错,因此您可能需要对此进行说明
SELECT
P.*
FROM
Products P
WHERE
NOT EXISTS
(
SELECT
*
FROM
Product_Search_Template PST
LEFT OUTER JOIN Properties P2 ON
P2.property = PST.property AND
P2.value = PST.value AND
P2.product_id = P.product_id
WHERE
P2.id IS NULL
)
在您的示例中,当组计数大于2时会发生什么情况?他们将被排除在外。我想你应该把它当作组计数>0谢谢,这确实有效。我将比较性能。为了使事情变得更复杂,我有另一个属性类型表要连接并以相同的方式进行过滤,但使用这种方法,应该很容易涉及到另一个表。谢谢,这是可行的,但我担心如果我必须将表连接到自身超过2次,它将如何执行。它将与任何其他解决方案一样执行,特别是子查询方法。将表连接到自身本身并不是性能杀手。请从属性p1、属性p2、产品pn中选择不同的p1.product_id、pn.product,其中p1.product_id=p2.product_id和p1.product='size'和p1.value='small'和p2.product='color'和p2.value='red'和pn.id=p1.product_id我测试了此查询。这将足够快。你是对的,属性名称并不重要,只是值。在实际表中,名称和值都是外键。我将动态构建SQL,所需的值来自数组。我最终需要在同一个查询中过滤另一个属性类型表。那么,你的意思是,如果它们的大小很小,或者分布范围很小,那么搜索“小”时应该对它们进行相同的处理?那不是我编码的目的。当我使用真正的键盘时,我会把它清理干净。
SELECT
prop1.product_id
FROM
properties prop1
JOIN properties prop2
ON prop1.product_id = prop2.product_id
WHERE
prop1.property = 'color' and prop1.value = 'red'
and prop2.property = 'size' and prop2.value = 'small'
SELECT
P.*
FROM
Products P
WHERE
NOT EXISTS
(
SELECT
*
FROM
Product_Search_Template PST
LEFT OUTER JOIN Properties P2 ON
P2.property = PST.property AND
P2.value = PST.value AND
P2.product_id = P.product_id
WHERE
P2.id IS NULL
)
SELECT
P.*
FROM
(
SELECT
PROP1.product_id,
COUNT(*) AS match_count
FROM
Properties PROP1
INNER JOIN Product_Search_Template PST ON
PST.property = PROP1.property AND
PST.value = PROP1.value
GROUP BY
PROP1.product_id
) SQ
INNER JOIN Products P ON
P.product_id = SQ.product_id
WHERE
SQ.match_count = (SELECT COUNT(*) FROM Product_Search_Template)