繁体   English   中英

我如何从 MySQL 表中的 select 行按一列分组,另一列具有所需值

[英]How do I select rows from a MySQL table grouped by one column with required values in another

我需要过滤某些属性存储在与所有必需属性匹配的连接表中的产品,即用户需要能够通过添加要求逐渐缩小搜索范围。

鉴于以下(简化的)产品属性表,问题实际上只涉及我认为的属性表,而不是连接:

id  product_id  property  value
---------------------------------
1   1           color     red
2   1           size      small
3   2           color     red
4   2           size      large

我如何获得价值既是“红色”又是“小”的所有 product_ids?

之前有人问过类似的问题,但没有完全回答。 一个解决方案涉及 COUNT 和 HAVING 来获取每组中的行数与所需值一样多的行,例如

SELECT product_id, count(*) AS group_count FROM properties where
value = 'red' OR value = 'small'
GROUP BY product_id
HAVING group_count = 2

这可行,但我担心性能,似乎会有更好的方法。

最终这将需要加入或至少用于过滤产品表:

id  name     
-------------
1   Product 1
2   Product 2

我忘了提到我有 2 个这些属性表加入了我需要过滤的产品,一个具有产品的常规属性,另一个具有可用的可配置选项(有点像变体)。 该方案是允许用户过滤产品,例如:“显示性别='男',品牌='耐克'和尺寸=='小'的产品”,其中性别和品牌是'属性'并且尺寸在选项中(可配置时添加到购物车)

使用带有计数的组的解决方案仍然适用于 2 个连接的表,但它会变得混乱,所需的组计数是第一个表上所需选项的数量乘以第二个表上的数字。

我可以从属性(和另一个表)中获取 id,然后只做一个 select where id IN(ids),匹配两个属性表的一组 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 DISTINCT p1.product_id, pn.name 
FROM properties p1, properties p2,
     productNames pn
WHERE p1.product_id = p2.product_id
AND p1.property = 'size' and value = 'small'
AND p2.property = 'color' and value = 'red'
AND pn.id = p1.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'

又一次遇到了属性值数据 model 的陷阱之一。

假设您想要“颜色”与“红色”匹配且“尺寸”与“小”匹配的产品(您在问题中并没有说属性实际上很重要,只是价值),问题的很大一部分是,您如何表示所需匹配的列表? 它们会作为分隔字符串传递,存储在临时表中,动态构建的 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
    )

.

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM