开发者

select items that have multiple matches in a normalized table

开发者 https://www.devze.com 2023-02-27 22:06 出处:网络
I have a table that stores a bunch of objects.Each object can have many colors which are stored in a normalized table connected by the object_id.

I have a table that stores a bunch of objects. Each object can have many colors which are stored in a normalized table connected by the object_id.

If I go

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

Then I get objects that are 'red' OR 'blue'. I need to get all objects that are 'red' AND 'blue'. If I go:

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

Then I get nothing as there's only one object_color in each line and it can't be both. Also, in actuality, the colors are id's with names in another table. I simplified everything here for the sake of the question.

I need to be able to search for an unlimited number of colors.开发者_高级运维

Thanks

EDIT:

object_color is only in the object_color table.

And any object will have any single color once.


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

Btw, you never mention from which table the object_color column derives. If it is from the object_color table:

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

The above query assumes that a given object row could have not have multiple object_color rows of the same color. However, as Joel C noted, if it were possible for an object to have multiple object_color rows of red or blue, then that requires a different query. :

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'
                        )

Yet another solution:

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


I prefer ON rather than 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' )
                            )

Assuming that it is not possible for an object to have many rows with same colour.


You'll need a multi join

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' ;


You can also use INTERSECT if it is supported in the SQL you're using.

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

This will intersect the two tables and only show rows that have both red and blue color matched with the same object name.

0

精彩评论

暂无评论...
验证码 换一张
取 消