Запрос SQL/критериев СОДЕРЖИТ ВСЕ?

Table A:        Table A_B:         Table B:
id | a          a_id | b_id        id | b
------          -----------        ------
1  | w          1    | 1           1  | s
2  | x          1    | 2           2  | t
3  | y          2    | 4           3  | u
4  | z          4    | 4           4  | v

Теперь я хотел бы иметь ВСЕ записи из таблицы A, ГДЕ B.id = 1 И B.id = 2.

На данный момент у меня есть следующий код:

SELECT *
FROM A a
JOIN A_B ab ON a.id    = ab.a_id
JOIN B b    ON ab.b_id = b.id

И тут я застрял. WHERE b.id IN (...) дает мне все записи из таблицы A, ГДЕ b.id = 1 OR b.id = 2конечно, а WHERE b.id = 1 AND b.id = 2 вообще не дает результатов...

Единственное возможное решение, которое я нашел, это использование INTERSECT:

SELECT *
FROM A a
JOIN A_B ab ON a.id    = ab.a_id
JOIN B b    ON ab.b_id = b.id
WHERE b.id = 1

INTERSECT

SELECT *
FROM A a
JOIN A_B ab ON a.id    = ab.a_id
JOIN B b    ON ab.b_id = b.id
WHERE b.id = 2

Но у меня может быть бесконечное количество ставок. Так что этот запрос станет очень медленным...

Разве нет чего-то вроде IN, который ведет себя так, как я хочу? И это должно быть реализовано с помощью Criteria Query:

Join<A, B> aB = root.join(A_.bs); // as this is a @ManyToMany relationship
...

Но я также был бы счастлив с чистым SQL-решением.


person Benjamin M    schedule 10.12.2013    source источник
comment
я не уверен, что правильно понял вопрос, но я думаю, что это случай левого соединения codinghorror.com/blog/2007/10/   -  person Sam    schedule 11.12.2013
comment
Ваш пример будет понятнее, если вы измените запись в A_B с 2,4 на 2,2. Затем укажите, что запись 2 в таблице A не должна возвращаться, несмотря на соответствие одному значению (поскольку она не соответствует другому значению).   -  person mdahlman    schedule 11.12.2013


Ответы (3)


Проверено на MySQL:

select TableA.id, count(*)
from tableA
join tableA_B on TableA.id=TableA_B.a_id
where b_id =1 or b_id=2
group by tableA.id
having count(*)=2

скрипт SQL здесь.

person neutrino    schedule 10.12.2013
comment
Это зависит от подсчета... поэтому будет возвращено слишком много записей, если, например, A_B дважды содержит запись 2,2. - person mdahlman; 11.12.2013

Должен признаться, я не особо слежу за вопросом и проблемой, но вы говорите, что это не работает:

SELECT *
FROM B b
LEFT JOIN A_B ab ON b.id    = ab.b_id
LEFT JOIN A a    ON ab.a_id = a.id
WHERE b.id IN (1,2)
person mrunion    schedule 10.12.2013
comment
Прочтите еще раз. Я нашел решение, используя INTERSECT. Но ваш запрос просто дает мне результаты из таблицы A, где b.id = 1 OR b.id = 2. Но мне нужны все записи из таблицы A, где b.id = 1 AND b.id = 2. - person Benjamin M; 11.12.2013

Насколько я понимаю, это отношение «многие ко многим», и вы хотите отфильтровать данные на основе идентификатора в таблице B.

Во-первых, ваш первый запрос кажется мне приемлемым; Я бы для ясности написал так:

select 
    a.id, a.a, b.id, b.b
from 
    A as a
    inner join A_B as ab on a.id = ab.a_id
    inner join B as b on ab.b_id = b.id;

Теперь, если вам нужны все записи, для которых b.id = 1 или b.id = 2, это должно работать:

select 
    a.id, a.a, b.id, b.b
from 
    A as a
    inner join A_B as ab on a.id = ab.a_id
    inner join B as b on ab.b_id = b.id
where
    b.id in (1,2);

Посмотрите этот пример SQLFiddle.

Надеюсь это поможет

person Barranka    schedule 10.12.2013
comment
Эй, спасибо. Я должен был написать скрипку SQL... Я изменил вашу: sqlfiddle.com/#!2/ 6628f/1 (Изменены записи в таблице A_B). Теперь результат должен содержать только a.id = 1, потому что это единственная запись, которая соответствует b.id = 1 И b.id = 2. - person Benjamin M; 11.12.2013