簡體   English   中英

在WHERE子句中避免多個SELECT

[英]Avoid multiple SELECT in WHERE clause

我正在嘗試增強在商家網站中發現的SQL錯誤。

我有兩個表:

------ Table "products" ------
| id_product | product_name |
-----------------------------
|          1 |      T-shirt |
|          2 |     Trousers |
|          3 |  Sweat-shirt |
|          4 |        Socks |

----------- Table "features" -----------
| id_product | feature | feature_value |
----------------------------------------
|          1 |   Color |           Red |
|          1 |    Size |             M |
|          1 |  Fabric |        Cotton |
|          2 |   Color |          Blue |
|          2 |    Size |             S |
|          2 |  Fabric |     Polyester |
|          3 |   Color |           Red |
|          3 |    Size |             L |
|          3 |  Fabric |          Wool |
|          4 |   Color |         White |
|          4 |    Size |             L |
|          4 |  Fabric |        Cotton |

我正在嘗試檢索具有以下功能的產品:

  • 顏色是紅色或藍色
  • 尺寸是M
  • 面料是棉的

我的查詢如下:

SELECT p.id_product
FROM products p
WHERE p.id_product IN (SELECT f.id_product FROM features f WHERE f.feature_value IN ("Red", "Blue"))
    AND p.id_product IN (SELECT f.id_product FROM features f WHERE f.feature_value = "M")
    AND p.id_product IN (SELECT f.id_product FROM features f WHERE f.feature_value = "Cotton")
GROUP BY p.id_product

(當然,實際上,我的表和查詢要比這復雜得多,我只關注有問題的部分)

如果選擇8個或更多功能,則WHERE子句中的多個SELECT會導致我的整個服務器速度變慢。 有沒有辦法避免在WHERE子句中進行這么多查詢?

編輯:例如,這是真正的查詢之一:

SELECT p.id_product id_product
FROM ps_product p 
INNER JOIN ps_category_product cp ON p.id_product = cp.id_product 
INNER JOIN ps_category c ON (c.id_category = cp.id_category AND c.nleft >= 6 AND c.nright <= 7 AND c.active = 1)
LEFT JOIN ps_stock_available sa ON (sa.id_product = p.id_product AND sa.id_shop = 1) 
INNER JOIN ps_product_shop product_shop ON (product_shop.id_product = p.id_product AND product_shop.id_shop = 1)
WHERE 1
AND product_shop.active = 1
AND product_shop.visibility IN ("both", "catalog")
AND p.id_manufacturer IN (5,4)
AND sa.quantity > 0
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 82)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 37248)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 181)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 37821)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 33907)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 33902)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 70)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 76)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 291)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 75)
AND p.id_product IN (SELECT id_product FROM ps_feature_product fp WHERE fp.id_feature_value = 44459)
GROUP BY id_product

您可以使用JOINHAVING子句:

SELECT p.id_product
FROM products p
JOIN features f
  ON p.id_product = f.id_product
GROUP BY p.id_product
HAVING COUNT(CASE WHEN f.feature_value IN ('Red', 'Blue') THEN 1 END) > 0
   AND COUNT(CASE WHEN f.feature_value = 'M' THEN 1 END) > 0
   AND COUNT(CASE WHEN f.feature_value = 'Cotton' THEN 1 END) > 0;

LiveDemo


甚至更短(MySQL):

HAVING SUM(f.feature_value IN ('Red', 'Blue')) > 0
   AND SUM(f.feature_value = 'M') > 0
   AND SUM(f.feature_value = 'Cotton') > 0;
SELECT
  P.id_product
FROM
  products P
  INNER JOIN features F
    ON P.id_product = F.id_product
WHERE
    (F.featurure = 'Color' AND F.feature_value IN ('red', 'blue'))
    OR (F.featurure = 'Size' AND F.feature_value IN ('M'))
    OR (F.featurure = 'Fabric' AND F.feature_value IN ('Cotton'))
GROUP BY
    P.id_product
HAVING
    COUNT(DISTINCT F.feature) = 3

HAVING條件表明,至少應有3個不同的匹配功能(這是您的搜索字段的數量)。

試試這個,希望對您有所幫助。

SELECT p.id_product,count(f.feature_value)
FROM products p, features f
where f.id_product=p.id_product 
and f.feature_value in ("Red","Blue") 
or f.feature_value = "M"
or f.feature_value = "Cotton"
group by p.id_product

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM