You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL查询需求:仅保留同时满足两个特征条件的产品

解决方法:筛选同时具备双特征的产品

你的需求很明确——要排除只满足单个特征的产品,只保留同时拥有符合条件的"Poids"和"Taille de l'écran"特征的产品。原查询用OR连接两个特征条件,所以只要满足其中一个就会被返回,这就是问题所在。下面给你几种靠谱的实现方式:

方法1:分组统计特征数量(最直观)

先筛选出所有符合两个特征条件的记录,然后按产品分组,确保每个产品至少有两条不同的符合条件的特征记录(对应两个特征):

SELECT P.*, F.*
FROM produits as P
JOIN fournisseur as F ON P.fournisseur = F.reffournisseur
JOIN liste_caracteristiques as Li ON P.refproduit = Li.refproduit
JOIN caracteristiques as C ON C.idCarac = Li.idCarac
WHERE P.typeProd = '1' 
  AND P.prixpublicindicatif <= 450
  AND (
    (C.libelleCarac = "Poids" AND C.valeur <= 1100)
    OR 
    (C.libelleCarac = "Taille de l'écran" AND C.valeur IN('15cm', '8.3cm'))
  )
GROUP BY P.refproduit  -- 按产品主键分组,确保每个产品只返回一次
HAVING COUNT(DISTINCT C.libelleCarac) = 2;  -- 确保同时拥有两个特征

说明:

  • COUNT(DISTINCT C.libelleCarac) = 2 保证了该产品同时存在符合条件的"Poids"和"Taille de l'écran"记录,排除了只满足单个特征的情况。
  • 如果你的数据库要求GROUP BY包含所有非聚合列(比如PostgreSQL、MySQL开启ONLY_FULL_GROUP_BY),可以把SELECT里的字段调整为聚合函数或者都加入GROUP BY,或者改用下面的方法。

方法2:两次关联特征表(精准匹配)

通过两次连接caracteristiquesliste_caracteristiques,分别匹配两个特征的条件,这样只有同时满足两个条件的产品才会被筛选出来:

SELECT P.*, F.*
FROM produits as P
JOIN fournisseur as F ON P.fournisseur = F.reffournisseur
-- 匹配符合重量条件的特征
JOIN liste_caracteristiques as Li_poids ON P.refproduit = Li_poids.refproduit
JOIN caracteristiques as C_poids ON C_poids.idCarac = Li_poids.idCarac
  AND C_poids.libelleCarac = "Poids" 
  AND C_poids.valeur <= 1100
-- 匹配符合屏幕尺寸条件的特征
JOIN liste_caracteristiques as Li_ecran ON P.refproduit = Li_ecran.refproduit
JOIN caracteristiques as C_ecran ON C_ecran.idCarac = Li_ecran.idCarac
  AND C_ecran.libelleCarac = "Taille de l'écran" 
  AND C_ecran.valeur IN('15cm', '8.3cm')
WHERE P.typeProd = '1' 
  AND P.prixpublicindicatif <= 450;

说明:

  • 这种方法逻辑非常直接,通过两次独立的关联,确保产品同时满足两个特征的条件。
  • 如果同一个产品有多个符合条件的同特征记录(比如多个Poids条目),可能会产生重复行,这时可以加DISTINCT来去重:SELECT DISTINCT P.*, F.*

方法3:使用EXISTS子查询(性能友好)

用两个EXISTS分别检查产品是否存在符合条件的两个特征记录,这种方法在大表上通常性能不错,因为不需要分组或多次连接:

SELECT P.*, F.*
FROM produits as P
JOIN fournisseur as F ON P.fournisseur = F.reffournisseur
WHERE P.typeProd = '1' 
  AND P.prixpublicindicatif <= 450
  -- 检查存在符合重量条件的特征
  AND EXISTS (
    SELECT 1
    FROM liste_caracteristiques as Li
    JOIN caracteristiques as C ON C.idCarac = Li.idCarac
    WHERE Li.refproduit = P.refproduit
      AND C.libelleCarac = "Poids" 
      AND C.valeur <= 1100
  )
  -- 检查存在符合屏幕尺寸条件的特征
  AND EXISTS (
    SELECT 1
    FROM liste_caracteristiques as Li
    JOIN caracteristiques as C ON C.idCarac = Li.idCarac
    WHERE Li.refproduit = P.refproduit
      AND C.libelleCarac = "Taille de l'écran" 
      AND C.valeur IN('15cm', '8.3cm')
  );

说明:

  • EXISTS只关心是否存在符合条件的记录,不需要返回具体数据,所以用SELECT 1即可,效率很高。
  • 这种方法不会产生重复行,不需要额外去重。

你可以根据自己数据库的实际情况(比如数据量、索引情况)选择最适合的方法~

内容的提问来源于stack exchange,提问作者Sydowh

火山引擎 最新活动