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 WHERE 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

Но мога да имам безкраен брой b.ids. Така че тази заявка ще стане наистина бавна...

Няма ли нещо като 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 Fiddle тук.

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 ИЛИ b.id = 2. Но искам всички записи от таблица A, където b.id = 1 И 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