Имя: Пароль:
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
Здесь можно обсудить любую тему при этом оставаясь на форуме для 1Сников, который нужен для работы. Ymryn