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:两次关联特征表(精准匹配)
通过两次连接caracteristiques和liste_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




