2012-06-25 4 views
2

У меня есть следующие структуры таблиц.MySQL требует нескольких значений из нескольких строк соединения

Таблица A

id name 
1  name1 
2  name2 

Таблица B

a_id b_id 
1  1 
1  2 

Как можно выбрать все строки таблицы А, которые имеют как b_id 1 и 2? Таблица B представляет собой таблицу сопоставления между таблицей A и другой таблицей, содержимое которой не имеет значения для этого вопроса.

Благодарим вас за внимание и помощь!

+0

Что SQL вы пробовали? – prodigitalson

+0

Мне нравится разнообразие ответов ниже. Спасибо всем за сообщение. Я медленно читаю их и реализую, прежде чем я выберу ответ. – Akaishen

+0

Итак, в вашем примере вам нужна строка, где id = 1 из таблицы A? –

ответ

6

Этот запрос использует COUNT(DISTINCT), чтобы обеспечить присутствие обоих значений. Если бы я не использовал DISTINCT может неправильно посчитать строки в TableB, которые выглядят так, как спички, когда он не должен:

a_id b_id 
1  1 
1  1 


select a.id, a.name 
from TableA a 
inner join (
    select a_id 
    from TableB 
    where b_id in (1, 2) 
    group by a_id 
    having count(distinct b_id) = 2 #this number matches no. of unique values in IN clause 
) b on a.id = b.a_id 

SQL Fiddle example

+1

Добавлен пример SQL Fiddle – RedFilter

+0

@RedFilter, но вы должны включить некоторые комментарии о том, почему правильность может быть сложной. например потребность в 'count (distict b_id) = 2' vs' count (b_id) = 2) ' –

+0

Downvoter поможет объяснить, почему? – RedFilter

1
SELECT * FROM A JOIN B ON A.id=B.a_id WHERE B.b_id IN(1,2); 
+0

Таблица B в этом запросе - фактически таблица сопоставления, в противном случае правильная :) –

+0

@ImreL true, но имеет ли это значение? Вы предпочли бы, чтобы он был написан с B, являющимся основной таблицей? – Cfreak

+2

@ImreL вы ошибаетесь, это приведет к ложному положительному значению для A.ID = 2, если таблица B имеет только одно из значений, например. (2,1) [вот пример] (http://sqlfiddle.com/#!2/4937e/1). –

0
SELECT TableA.* FROM TableA WHERE TableA.id IN(
SELECT TableB.a_id FROM TableB WHERE TableB.b_id IN(1,2)) 
1

Вот что я мог придумать, это использует один подзапрос.

SELECT * FROM table_a a1 
    JOIN table_b b1 
    ON a1.id = b1.a_id 
WHERE b1.b_id = 1 AND 
    EXISTS( 
     SELECT b2.b_id 
      FROM table_b b2 
     WHERE a1.id = b2.a_id 
      AND b2.b_id = 2 
    ) 

Не знаю SQL Скрипки существует, но here is one показывая его работать!

+0

Я не рекомендую этот подход: как только ваш список значений возрастает, вам нужно добавить дополнительные подзапросы EXISTS (еще один для каждого дополнительного значения), и производительность быстро станет проблемой. – RedFilter

+0

Я никогда не говорил, что это был самый эффективный :) Опять же, ОП никогда не говорил, что список идентификаторов также был динамическим. – nickb

1

Я возьму удар в этом тоже с автообъединением:

SELECT A.* FROM B B1 
JOIN B B2 ON B2.a_id = B1.a_id 
JOIN A ON A.id = B1.a_id 
WHERE B1.b_id = 1 AND B2.b_id = 2 

Я испытал это, и она работает. Если (B.a_id, B.b_id) не является уникальным, тогда вам понадобится DISTINCT, чтобы избежать дублирования.

2

Правильность может быть сложной в вопросе, подобном этому, поскольку в ваших образцовых данных отсутствуют ключевые случаи. Повторяющиеся значения для B_ID и возможность того, что он может содержать один из идентификаторов, но не оба

например.

| A_ID | B_ID | 
--------------- 
| 1 | 1 | 
| 1 | 2 | 
| 2 | 1 | 
| 2 | 1 | 

Лучший подход заключается в использовании Имея (Distinct Count) = количество идентификаторов (RedFilter's), поскольку его легко добавить

Две другие варианты Подробнее ID являются использовать или несколько EXISTS или в пунктах (NickB's) или присоединиться и фильтровать несколько раз (см. Ниже), но может стать чересчур длинным, если вам нужно добавить дополнительные идентификаторы.

SELECT DISTINCT a.id, 
     a.name 
FROM TableA a 
    INNER JOIN TableB b1 
    ON a.id = b1.a_id 
     and b1.b_id = 1 
    INNER JOIN TableB b2 
    ON a.id = b2.a_id 
     and b2.b_id = 2 

DEMO

+0

Я не рекомендую этот подход: как только ваш список значений возрастает, вам нужно добавить больше объединений (еще один для каждого дополнительного значения), и производительность быстро станет проблемой. – RedFilter

+0

@RedFilter, но вы уже взяли хороший, но отлично, я сделаю его более ясным. –

+0

@RedFilter хорошо обновлен. –

Смежные вопросы