Лучший способ требовать в SQL, чтобы столбец содержал каждое указанное значение - PullRequest
3 голосов
/ 05 апреля 2011

Представьте, что у вас есть две таблицы с отношениями один ко многим.

В этом примере я предлагаю две таблицы: Персона и Дома.Таблица персон содержит имена людей и дает им идентификатор.Стол домов, содержит ассоциацию домов с человеком.PID присоединяется к «Person.ID»

И в этой крошечной БД у человека может не быть домов или много домов.

enter image description here

Я надеюсь, что нарисовал это правильно.

Как мне написать выборку, которая возвращает всех с каждый указанным типом дома?

Допустим, это действительные «Типы» в таблице домов:

Коттедж, Главная, Особняк, Космодром.

Я хочу вернуть всех, в таблице Person, у которых есть космодром и Коттедж.

Лучшее, что я мог придумать, было следующее:

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 ]

9 голосов
/ 05 апреля 2011

Пункт 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 голос
/ 05 апреля 2011
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

Чтобы найти идентификационные номера каждого человека, у которого есть коттедж и , особняк, сгруппируйте его по идентификационному номеру, ограничьте вывод коттеджами и особняками и подсчитайте различные типы.1004 *

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

person_id
--
1

Вы можете использовать этот запрос в объединении, чтобы получить все столбцы из таблицы person.

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;

Спасибо Джо за указание на ошибку в моем счетчике ().

0 голосов
/ 05 апреля 2011

Не уверен насчет производительности на этом, но здесь идет:

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.

...