Как выбрать несколько записей, используя AND в левой части JOIN - PullRequest
1 голос
/ 01 апреля 2011

У меня есть простое требование, но я не могу правильно сформулировать оператор SELECT, чтобы он дал желаемый результат.

У меня есть две таблицы: -

  1. Персональная таблица с ID и другой разной информацией
  2. Таблица лицензий с идентификатором для подключения и несколькими записями на человека (10-15)

Моя цель - получить всех людей с синей лицензией и белой лицензией (например).

Использование:

SELECT distinctrow person.ID AS client_ID, postcode, locality 
FROM (person INNER JOIN licences ON person.ID = licences.client_ID)
WHERE licence LIKE '%Blue%' **OR** licence LIKE '%White%'

конечно, мне возвращаются люди, у которых есть, а НЕ оба.

Использование:

SELECT distinctrow person.ID AS client_ID, postcode, locality 
FROM (person INNER JOIN licences ON person.ID = licences.client_ID)
WHERE licence LIKE '%Blue%' **AND** licence LIKE '%White%'

конечно не возвращает результатов (как это могло быть?).

Это действительно упрощенный пример, так как я собираю 5 таблиц во вложенном JOIN, для которых у всех есть критерии (входящие в 40 с лишним переменных $ _GET!) ... но это то, где я застрял. Я использовал И в ВНУТРЕННЕМ СОЕДИНЕНИИ, а не ГДЕ, без каких-либо изменений в результате. Я выпил много пива, все еще без изменений:)

Я знаю, что раскрываю свое незнание даже основ, но, конечно, мне не нужно помещать SELECT в SELECT? Может быть, влево или вправо?

Я чувствую, что собираюсь изучить кое-что элементарное здесь, так что включите это!

Ответы [ 4 ]

3 голосов
/ 01 апреля 2011
SELECT  *
FROM    person p
WHERE   (
        SELECT  COUNT(DISTINCT licence)
        FROM    licences l
        WHERE   l.client_id = p.id
                AND l.licence IN ('white', 'blue')
        ) = 2

или

SELECT  DISTINCT p.*
FROM    person p
JOIN    licences l
ON      l.client_id = p.id
        AND l.licence IN ('white', 'blue')
GROUP BY
        p.id
HAVING  COUNT(DISTINCT licence) = 2

В зависимости от распределения данных (сколько лицензий на человека у вас есть), один из запросов будет более эффективным.

2 голосов
/ 01 апреля 2011

Попробуйте:

SELECT person.*
FROM person
WHERE EXISTS (SELECT 1 FROM licenses 
               WHERE licenses.client_ID = person.ID 
                 AND licence LIKE '%Blue%')
AND   EXISTS (SELECT 1 FROM licenses 
               WHERE licenses.client_ID = person.ID 
                 AND licence LIKE '%White%')

В зависимости от вашей схемы и размера таблицы, это может быть довольно медленно, хотя

1 голос
/ 01 апреля 2011

Похоже, ИНТЕРСЕКТ будет работать. Вы можете выбрать все синие, ИНТЕРСЕКТ выбрать все белые.

SELECT distinctrow person.ID AS client_ID, postcode, locality 
FROM person INNER JOIN licences ON person.ID = licences.client_ID
WHERE licence LIKE '%Blue%'
INTERSECT
SELECT distinctrow person.ID AS client_ID, postcode, locality 
FROM person INNER JOIN licences ON person.ID = licences.client_ID
WHERE licence LIKE '%White%'

(или что-то подобное. Я не очень знаком с MySql.)

РЕДАКТИРОВАТЬ: Неважно, MySql не поддерживает его. Вот что я получаю, пытаясь ответить на вопрос MySql

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

Поскольку синяя и белая лицензии существуют в отдельной записи в таблице лицензий, вам нужно будет дважды присоединиться к этой таблице, например:

SELECT person.ID AS client_ID, postcode, locality 
FROM person 
JOIN licences l1 ON person.ID = l1.client_ID
JOIN licences l2 ON person.ID = l2.client_ID
WHERE l1.license LIKE '%Blue%' AND l2.license LIKE '%White%'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...