Имя: Пароль:
IT
 
SQL: JOIN с "ленивым" условием
,
0 Asmody
 
13.11.15
16:24
Такая задачка:
Пусть есть таблица A с полями A1 и A2 типа integer и A_DATA типа varchar, и таблица B с полями B_ID типа integer и B_DATA типа varchar.
Требуется в запросе получить строки (A_DATA, B_DATA), соединив таблицы по A1=B_ID, а если такой строки нет, то по A2=B_ID (аналог "ленивого" ИЛИ).
1 User_Agronom
 
13.11.15
16:28
выбор А.А_дата, Б.Б_Дата из А кАК А
левое соединение Б КАК Б
По A1=B_ID где не Б.Б_Дата есть нулл

объединить все

другая таблица
2 Asmody
 
13.11.15
16:31
(1)
"левое соединение Б КАК Б По A1=B_ID где не Б.Б_Дата есть нулл" — это просто внутреннее соединение
3 ViSo76
 
13.11.15
16:34
И что так не прокатывает?

выбор
    А.А_дата,
    Б.Б_Дата
из
    А кАК А

    левое соединение Б КАК Б
        По A1=B_ID Или A2=B_ID
4 Asmody
 
13.11.15
16:36
(3) Так выберутся строки и с А1, и с А2. Но А2 нужно искать тогда и только тогда, когда А1 не найдено.
5 PR третий
 
13.11.15
16:38
(0) Делаешь ЛС А и Б, а потом еще раз ЛС с Б, уже зная в первом соединении, есть запись в Б или нет.
6 butterbean
 
13.11.15
16:43
(4)

ВЫБОР
    А.А_дата,
    Б.Б_Дата
из
    А кАК А

    левое соединение Б КАК Б
ПО ВЫБОР КОГДА A1=B_ID ТОГДА ИСТИНА ИНАЧЕ A2=B_ID КОНЕЦ
7 ViSo76
 
13.11.15
16:46
выбор
    А.А_дата,
    Б.Б_Дата
из
    А кАК А

    левое соединение Б КАК Б
        По A1=B_ID Или ( A1<>B_ID A2=B_ID )
8 ViSo76
 
13.11.15
16:47
(7) Точнее

выбор
    А.А_дата,
    Б.Б_Дата
из
    А кАК А

    левое соединение Б КАК Б
        По A1=B_ID Или ( A1<>B_ID И A2=B_ID )
9 ViSo76
 
13.11.15
16:48
(4) Приз в студию
10 Asmody
 
13.11.15
16:51
(6) (8) не пойдет
11 Garykom
 
гуру
13.11.15
16:52
(0) уже было не так давно полностью тоже самое но без А и Б
12 Asmody
 
13.11.15
16:54
A:
(1, 2, A)
(3, 4, B)

B:
(1, a)
(2, b)
(4, c)

в результате должно быть:
(A, a)
(B, c)
13 Asmody
 
13.11.15
16:55
Даже вот так:

A:
(1, 2, A)
(3, 4, B)
(5, 6, С)

B:
(1, a)
(2, b)
(4, c)

в результате должно быть:
(A, a)
(B, c)
14 PR третий
 
13.11.15
16:55
(5) Хотя лучше А ЛС Б ЛС Б
Первое ЛС по A1=B_ID, второе по A2=B_ID.
А в поле ВЫБОР.
15 Ненавижу 1С
 
гуру
13.11.15
16:59
выбрать
  A_DATA,
CASE WHEN NOT Б1.B_ID IS NULL THEN Б1.B_DATA ELSE Б2.B_DATA END
из А
левое соединение Б как Б1 по А.A1=Б1.B_ID
левое соединение Б как Б2 по А.A2=Б2.B_ID
16 Asmody
 
13.11.15
17:01
(15) останутся будут строки из А, для которых нет B_ID
17 ViSo76
 
13.11.15
17:02
(10) Ты уверен что (8) не прокатит?
18 Ненавижу 1С
 
гуру
13.11.15
17:02
+(16) ДОбавь

ГДЕ
  НЕ(Б1.B_ID IS NULL И Б2.B_ID IS NULL)
19 Asmody
 
13.11.15
17:11
(17) вот тут можно потренироваться
http://kripken.github.io/sql.js/GUI/

заготовка примера

DROP TABLE IF EXISTS A;
DROP TABLE IF EXISTS B;

CREATE TABLE A (a1 integer, a2 integer, a_data varchar);
CREATE TABLE B (b_id integer, b_data varchar);

INSERT INTO A VALUES (1,2,'A');
INSERT INTO A VALUES (3,4,'B');
INSERT INTO A VALUES (5,6,'C');

INSERT INTO B VALUES (1,'a');
INSERT INTO B VALUES (2,'b');
INSERT INTO B VALUES (4,'c');
20 Ненавижу 1С
 
гуру
13.11.15
17:17
вот

SELECT
  A_DATA,
CASE WHEN NOT B1.B_ID IS NULL THEN B1.B_DATA ELSE B2.B_DATA END as b_data
FROM A
LEFT JOIN B AS B1 ON A.A1=B1.B_ID
LEFT JOIN B AS B2 ON A.A2=B2.B_ID
WHERE NOT(B1.B_ID IS NULL AND B2.B_ID IS NULL)
21 Asmody
 
13.11.15
17:18
У меня вышло так:

SELECT a_data, CASE WHEN NOT b1.b_data IS NULL THEN b1.b_data ELSE b2.b_data END as b_data
FROM A
LEFT JOIN B as B1 ON a1=b1.b_id
INNER JOIN B as B2 ON a2=b2.b_id
22 Ненавижу 1С
 
гуру
13.11.15
17:22
(21) а если a2=b2.b_id не выполнится строка пропадет
23 Asmody
 
13.11.15
17:22
да, точно
24 sda553
 
15.11.15
01:39
select isnull(a_1.adata,a_2.adata).b.data
from b
left join a a_1 on a_1.a1=b.id
left join a a_2 on a_2.a2=b.id
25 Asmody
 
16.11.15
09:34
(24) Не, возвращает 2 строки, когда а1 и а2 находятся.
26 Ненавижу 1С
 
гуру
16.11.15
10:20
я выиграл в (20). Где мой приз?
27 Гёдза
 
16.11.15
10:25
(25)  А разве отношение не 1 к 1?
28 Ёпрст
 
16.11.15
10:28
SELECT
  A_DATA,
coalesce(B1.B_DATA,B2.B_DATA) as b_data
FROM A
LEFT JOIN B AS B1 ON A.A1=B1.B_ID
LEFT JOIN B AS B2 ON A.A2=B2.B_ID
WHERE NOT(coalesce(B1.B_DATA,B2.B_DATA)IS NULL)
29 elCust
 
16.11.15
10:50
SELECT * FROM (SELECT a.a_data, b_data From A Left join B as B ON a.a1=b.b_id UNION ALL SELECT a.a_data, b_data From A Left join B as B ON a.a2=b.b_id) AS tem WHERE b_data NOT NULL
30 Ёпрст
 
16.11.15
11:10
(29) лишняя строка возвращается (проверка в (19)  )
31 rabbidX
 
16.11.15
11:40
(13) (А,b) нет в результате из-за того, что есть (А,а)?
32 Asmody
 
16.11.15
12:02
(31) ага
33 sda553
 
18.11.15
07:10
(25) неа, одну
но может задвоится, но данные вернык. можно для устранения задвоения добавить distinct или group