选择规范化表中具有多个匹配项的项

时间:2011-04-20 22:21:11

标签: php mysql search normalization

我有一个存储一堆对象的表。每个对象可以有许多颜色,这些颜色存储在由object_id连接的规范化表中。

如果我去

SELECT `object_name` FROM `objects`
  LEFT JOIN `object_color` USING `object_id`
    WHERE `object_color` IN ('red', 'blue');

然后我得到'红色''蓝色'的对象。我需要获得所有“红色”“蓝色”的对象。如果我去:

SELECT `object_name` FROM `objects`
  LEFT JOIN `object_color` USING `object_id`
    WHERE `object_color` = 'red' AND `object_color` = 'blue';

然后我得不到任何东西,因为每一行中只有一个object_color,它不能同时存在。另外,实际上,颜色是另一个表中带有名称的id。为了这个问题,我在这里简化了一切。

我需要能够搜索无限数量的颜色。

由于

修改

object_color仅在object_color表中。

任何物体都会有一次任何一种颜色。

4 个答案:

答案 0 :(得分:4)

Select object_name
From objects
Where object_color In('red','blue')
Group By object_name
Having Count(Distinct object_color) = 2

顺便说一句,你从不提及object_color列派生的表格。如果它来自object_color表:

Select O.object_name
From objects As O
    Join object_color As C
        On C.object_id = O.object_id
Where C.object_color In('red','blue')
Group By O.object_name
Having Count(Distinct C.object_color) = 2

上述查询假定给定的object行可能没有多个相同颜色的object_color行。但是,正如Joel C所指出的,如果object有可能有多个object_color行的红色或蓝色,那么这需要不同的查询。 :

Select ...
From objects As O
Where O.object_id In    (
                        Select C1.object_id
                        From object_color As C1
                        Where C1.object_color = 'red'
                        )
    And O.object_id In  (
                        Select C1.object_id
                        From object_color As C1
                        Where C1.object_color = 'blue'
                        )

又一个解决方案:

Select O.object_name
From objects As O
    Join    (
            Select C1.object_id, C1.object_color
            From object_color As C1
            Where C1.color In('red','blue')
            Group By C1.object_id, C1.object_color
            ) As Z
        On Z.object_id = O.object_id
Group By O.object_name
Having Count(*) = 2

答案 1 :(得分:2)

我更喜欢ON而不是USING

SELECT o.object_name
FROM objects o
  JOIN object_color oc
    ON o.object_id = oc.object_id
WHERE oc.object_color IN ( 'red', 'blue' )
GROUP BY o.object_id
HAVING COUNT(o.object_id) = ( SELECT COUNT(*)
                              FROM ( 'red', 'blue' )
                            )

假设一个对象不可能有许多具有相同颜色的行。

答案 2 :(得分:1)

您需要多次加入

SELECT `object_name` FROM `objects`
  LEFT JOIN `object_color` USING `object_id`
    WHERE `object_color` = 'red'
  LEFT JOIN `object_color` USING `object_id`
    WHERE `object_color` = 'blue' ;

答案 3 :(得分:0)

如果您正在使用的SQL支持INTERSECT,也可以使用它。

SELECT object_name
FROM objects o, objects_color oc
WHERE object_color = 'red'
and o.object_id = oc.object_id

INTERSECT

SELECT object_name
FROM objects o, objects_color oc
WHERE object_color = 'blue'
and o.object_id = oc.object_id

这将与两个表相交,仅显示红色和蓝色与相同对象名称匹配的行。