我有以下数据库结构:
表汽车:
+----+-----------------------+
| id | few other columns.... |
+----+-----------------------+
| 1 | ... |
| 2 | ... |
| 3 | ... |
+----+-----------------------+
表属性:
+----+-------+
| id | name |
+----+-------+
| 1 | title |
| 2 | type |
| 3 | brand |
| 4 | color |
+----+-------+
表 cars_properties :
+----+--------+-------------+------------+
| id | car_id | property_id | txt |
+----+--------+-------------+------------+
| 1 | 1 | 1 | Volvo V70 |
| 2 | 1 | 2 | personal |
| 3 | 1 | 3 | Volvo |
| 4 | 1 | 4 | white |
| 5 | 2 | 1 | Volvo VV |
| 6 | 2 | 2 | personal |
| 7 | 2 | 3 | Volvo |
| 8 | 2 | 4 | blue |
| 9 | 3 | 1 | Volvo XXL |
| 10 | 3 | 2 | truck |
| 11 | 3 | 3 | Volvo |
| 12 | 3 | 4 | white |
+----+--------+-------------+------------+
我想让所有在一个或多个属性中具有唯一/重复值的汽车。目前,我正在使用此SQL模式来获取汽车类型和品牌的重复项:
SELECT cars.id FROM cars
LEFT JOIN cars_properties AS cp_0 ON cp_0.car_id = cars.id AND cp_0.property_id = 2 # => type
LEFT JOIN cars_properties AS cp_1 ON cp_1.car_id = cars.id AND cp_1.property_id = 3 # => brand
INNER JOIN (
SELECT cp_0.txt AS type_txt, cp_1.txt AS brand_txt FROM cars
LEFT JOIN cars_properties AS cp_0 ON cp_0.car_id = cars.id AND cp_0.property_id = 2
LEFT JOIN cars_properties AS cp_1 ON cp_1.car_id = cars.id AND cp_1.property_id = 3
GROUP BY cp_0.txt, cp_1.txt
HAVING COUNT(cars.id) > 1
) dupes ON cp_0.txt=dupes.type_txt AND cp_1.txt=dupes.brand_txt;
预期结果是:
+----+
| id |
+----+
| 1 |
| 2 |
+----+
说明:id = 1和2的两辆车都有type
和brand
,它们出现在多辆车中(多次)。
对于独特的汽车,我只是改变:HAVING COUNT(cars.id) = 1
我希望找到属性组合仅存在于一辆汽车中的所有行(一次)。
它工作正常,但是我想检查的属性超过2个,速度非常慢。 我无法更改数据库结构,并且我不确定如何优化查询,或者是否有更好的方法来实现此目的。
感觉我需要实现计数器表,其中每个属性id和值(txt)也会在汽车中存储相应的出现次数,并在每次插入/更新/删除时更新此计数器......但我仍然希望有一些更好的SQL,这可能有所帮助。你知道吗?非常感谢任何建议,谢谢!
PS:我试图为它创建小提琴,但在构建模式后,我无法在其上运行任何SQL。要使用数据快速设置数据库,您可以查看SQL Fiddle