在SQL中要求列包含每个指定值的更好方法

时间:2011-04-05 15:49:50

标签: sql select one-to-many

想象一下,你有两张桌子,有一对多的关系。

对于这个例子,我建议有两个表:Person和Homes。 人员表中包含人员姓名,并为其提供身份证明。家庭表,持有一个人的家庭协会。 PID加入“Person.ID”

而且,在这个小小的数据库中,一个人可以没有家,也没有许多家。

enter image description here

我希望我画得正确。

如何编写一个select,它会返回每个每个指定的房屋类型的所有人?

假设这些是家庭表中有效的“类型”:

  

Cottage,Main,Mansion,Spaceport。

我想在Person表中返回一个拥有spaceport 一个Cottage的人。

我能想出的最好的是:

SELECT DISTINCT( p.name ) AS name
FROM person p
    INNER JOIN homes h ON h.pid = p.id
WHERE 'spaceport' in (
    SELECT DISTINCT( type ) AS type
    FROM homes
    WHERE pid = p.id
)
AND 'cottage' in (
    SELECT DISTINCT( type ) AS type
    FROM homes
    WHERE pid = p.id
)

当我写这篇文章时,它有效,但我很确定必须有更好的方法。

3 个答案:

答案 0 :(得分:9)

此处的HAVING子句将保证返回的人员两种类型,而不仅仅是其中一种。

SELECT p.name
    FROM person p
        INNER JOIN homes h
            ON p.id = h.pid
                AND h.type IN ('spaceport', 'cottage')
    GROUP BY p.name
    HAVING COUNT(DISTINCT h.type) = 2

答案 1 :(得分:1)

select * from homes;

home_id  person_id  type
--
1        1          cottage
2        1          mansion
3        2          cottage
4        3          mansion
5        4          cottage
6        4          cottage

要找到同时包含小屋大厦的每个人的ID号,按照ID号分组,将输出限制为小屋和大厦,并计算不同的类型。

select person_id
from homes
where type in ('cottage','mansion')
group by person_id
having count(distinct type) = 2;

person_id
--
1

您可以在联接中使用此查询来获取人员表中的所有列。

select person.* 
from person
inner join (select person_id
            from homes
            where type in ('cottage','mansion')
            group by person_id
            having count(distinct type) = 2) T
on person.person_id = T.person_id;

感谢Joe指出我的count()中的错误。

答案 2 :(得分:0)

不确定这个的性能,但这里有:

SELECT PID FROM (
    SELECT PID, COUNT(PID) cnt FROM (
        SELECT DISTINCT PID, Type FROM Homes 
        WHERE Type IN ('Type1', 'Type2', 'Type3')
    ) a
    GROUP BY PID
) b
WHERE b.cnt = 3

您必须动态生成IN子句以及WHERE b.CNT子句。