2

So I'm just starting to learn SQL, and hit upon the following problem. Suppose I have a table with 3 columns like so:

ID    | Property_Name    | Property_Value
1     | Color            | "Blue"
1     | Size             | "Large"
2     | Color            | "Red"
3     | Color            | "Orange"
3     | Size             | "Small"
4     | Color            | "Blue"
4     | Size             | "Large"
...

Now, suppose I want to find the IDs that have Color=Blue and Size=Large (aka. ID 1 and 4), how would I best do this. The best way I came up with is the following, but it seems clunky...

SELECT ID FROM PropertyTable
WHERE
ID IN (
        SELECT ID FROM PropertyTable WHERE
        Property_Name='Color' AND Property_Value='blue' )
AND
(Property_Name='Size' AND Property_Value='Large')

Thank you :)

EDIT: Forgot to add preformat tags to the example table text. Just did so.

4

3 回答 3

6

自己加入怎么样?

SELECT T1.ID
FROM PropertyTable T1
JOIN PropertyTable T2 ON T1.ID = T2.ID
WHERE
        T1.PropertyName = 'Color' AND T1.PropertyValue = 'Blue'
    AND
        T2.PropertyName = 'Size' AND T2.PropertyValue = 'Large'

这是一个SQLFiddle

于 2013-08-15T20:54:29.517 回答
0

这是“set-within-sets”子查询的一个示例。我认为最通用的方法是使用带有having子句的聚合:

select ID
from PropertyTable pt
group by ID
having sum(case when Property_Name='Color' AND Property_Value='blue' then 1 else 0 end) > 0 and
       sum(case when Property_Name='Size' AND Property_Value='Large' then 1 else 0 end) > 0;

该语句的每个子句都在having计算与每个条件匹配的行数。

我喜欢这个的原因是因为它非常通用如果你想添加另一个属性,你只需添加类似的子句:

select ID
from PropertyTable pt
group by ID
having sum(case when Property_Name='Color' AND Property_Value='blue' then 1 else 0 end) > 0 and
       sum(case when Property_Name='Size' AND Property_Value='Large' then 1 else 0 end) > 0 and
       sum(case when Property_Name = 'Heating' and Property_Value = 'Gas' then 1 else 0 end) > 0;

如果您想要这三个条件中的任何一个,那么您将使用or

select ID
from PropertyTable pt
group by ID
having sum(case when Property_Name='Color' AND Property_Value='blue' then 1 else 0 end) > 0 or
       sum(case when Property_Name='Size' AND Property_Value='Large' then 1 else 0 end) > 0 or
       sum(case when Property_Name = 'Heating' and Property_Value = 'Gas' then 1 else 0 end) > 0;
于 2013-08-15T21:45:43.930 回答
0

如果颜色和大小的值不重叠,那么您可以执行类似的操作。

SELECT
 ID
FROM PropertyTable
WHERE Property_Name IN ('Color','Size') 
 AND Property_Value IN ('Blue','Large')
GROUP BY
 ID
HAVING 
 COUNT(ID) = 2

如果它们确实重叠,那么试试这个。

SELECT
 ID
FROM PropertyTable
WHERE (Property_Name = 'Color' AND Property_Value = 'Blue')
 OR (Property_Name = 'Size' AND Property_Value = 'Large')
GROUP BY
 ID
HAVING 
 COUNT(ID) = 2
于 2013-08-15T20:59:21.080 回答