2012-02-20 9 views
0

Следующая таблица имеет идентификационный номер людей, наряду с городами они работали в:SQL: запросы на основе нескольких записей

PERSON_NO | CITY_NAME 
--------------------- 
1   | City A 
2   | City B 
3   | City A 
3   | City B 
3   | City C 
4   | City A 
4   | City B 
4   | City C 

Как я смогу получить PERSON_NO всех людей, которые жили во всех трех городах, A, B и C?

Я хочу вернуть

PERSON_NO 
--------- 
3 
4 

Спасибо, еще раз. У меня не было такого большого опыта работы с SQL, и поэтому я не уверен, что делать.

+2

Это домашнее задание? Найдите '[реляционное деление]' или ['sql-match-all'] (http://stackoverflow.com/questions/tagged/sql-match-all) –

+0

@ypercube Мне даже не приходило в голову сегодня. Я оставлю его удаленным, пока мы не узнаем ... –

+0

@ Майкл: Я пометил его для закрытия по ошибке. Я думал, что он идентичен предыдущему вопросу того же пользователя. –

ответ

1

Вы можете использовать несколько EXISTS() пункты:

select a.PERSON_NO 
    from personTable a 
    where exists (select 1 from personTable where PERSON_NO = a.PERSON_NO 
       and CITY_NAME = 'City A') 
    and exists (select 1 from personTable where PERSON_NO = a.PERSON_NO 
       and CITY_NAME = 'City B') 
    and exists (select 1 from personTable where PERSON_NO = a.PERSON_NO 
       and CITY_NAME = 'City C') 
2

Другой способ просто присоединиться к таблице себе несколько раз.

SELECT DISTINCT Person_No FROM mytable 
INNER JOIN mytable mt2 on (cityname='city b' and mt1.person_no=mt2.person_no) 
INNER JOIN mytable mt3 on (cityname='city c' and mt1.person_no=mt3.person_no) 
WHERE cityName='city a' 

При первом изучении SQL большинство студентов не понимают, что вполне законно включать одну и ту же таблицу в запрос несколько раз. Есть много проблем, которые можно решить таким образом.

+1

+1 для использования объединений и для учащегося. Верно, что новые пользователи SQL часто рассматривают таблицу в своей статье как «специальную» как-то в том, что ее присоединяют, и такие, и забывают, что ее можно воссоздать так же, как и любой другой :) – Jordan

3

Если вы в SQL Server 2000 или выше, вы можете использовать INTERSECT:

select PERSON_NO from table1 where CITY_NAME='City A' 
intersect 
select PERSON_NO from table1 where CITY_NAME='City B' 
intersect 
select PERSON_NO from table1 where CITY_NAME='City C' 
0

Я хотел бы сделать это с агрегацией и HAVING. Предполагая, что нет повторы:

SELECT person_no, count(*) 
    FROM mytable 
    WHERE city_name IN ('City A', 'City B', 'City C') 
    GROUP BY person_no 
HAVING count(*) = 3 

Это имеет преимущество попадания в таблицу только один раз, что объединение не может сделать.

-1

Попробуйте

SELECT PERSON_NO 
FROM  YOURTABLENAME 
WHERE CITY_NAME = 'City A' 
     AND CITY_NAME = 'City B' 
     AND CITY_NAME = 'City C' 
+0

-1 Нет _single_ CITY_NAME может быть равно более одного значения в одно и то же время, поэтому это никогда не вернет строки. –

+0

А, ок, я тоже совсем новичок в этом .. подумал, что это возможно ... спасибо за разъяснение – MonteCristo

0

фактически не проверить это, но это общая идея должна работать:

SELECT DISTINCT PERSON_ID 
FROM YOUR_TABLE T1 
WHERE 
    NOT EXISTS (
     SELECT CITY_NAME -- All cities. 
     FROM YOUR_TABLE T2 
     EXCEPT -- Or may be "MINUS", depending on your DBMS. 
     SELECT CITY_NAME -- Cities the user worked in. 
     FROM YOUR_TABLE T3 
     WHERE T1.PERSON_NO = T3.PERSON_NO 
    ) 

На простом английском языке:

  • Для каждого отдельного человека, найти set difference между все города и города она работала в.
  • Если эта разница пуста, человек работал во всех городах.
+0

Как ни странно, мой, кажется, единственный общий ответ, предложенный до сих пор.Все остальные ответы потребуют изменения текста SQL, если город добавлен/изменен/удален в таблице. –