簡體   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