Ответ 1
вы можете использовать этот подход, но вы должны быть уверены, что внутренний выбор возвращает только одну строку.
SELECT A.id,
(select B.id from B where A.name = B.name) as B_ID
FROM A
Мне нужно смоделировать эффект левого соединения без использования клавиши "левого соединения".
У меня есть две таблицы: A и B, как с столбцами id
, так и name
. Я хотел бы выбрать все dbids для обеих таблиц, где имя в равно имени в B.
Я использую это для синхронизации, поэтому в начале B пусто (поэтому у меня будут пары с id из A со значением, а id из B - null). Позже у меня будет сочетание пар со значением - значением и значением - null.
Обычно это будет:
SELECT A.id, B.id
FROM A left join B
ON A.name = B.name
Проблема заключается в том, что я не могу использовать left join
и хотел бы знать, можно ли/как сделать то же самое.
вы можете использовать этот подход, но вы должны быть уверены, что внутренний выбор возвращает только одну строку.
SELECT A.id,
(select B.id from B where A.name = B.name) as B_ID
FROM A
Просто отмените таблицы и используйте вместо них правое соединение.
SELECT A.id,
B.id
FROM B
RIGHT JOIN A
ON A.name = B.name
Я не знаком с java/jpa. Используя чистый SQL, здесь один подход:
SELECT A.id AS A_id, B.id AS B_id
FROM A INNER JOIN B
ON A.name = B.name
UNION
SELECT id AS A_id, NULL AS B_id
FROM A
WHERE name NOT IN ( SELECT name FROM B );
В SQL Server, например, вы можете использовать оператор *=
для создания левого соединения:
select A.id, B.id
from A, B
where A.name *= B.name
Другие базы данных могут иметь несколько иной синтаксис, если такой оператор существует вообще.
Это старый синтаксис, используемый перед ключевым словом join
. Разумеется, если это возможно, используйте ключевое слово join
. Старый синтаксис может даже не работать в более новых версиях базы данных.
Вы можете использовать подзапросы, например:
select a.id
, nvl((select b.id from b where b.name = a.name), "") as bId
from a
Я могу думать только о двух путях, которые до сих пор не были даны. Мои последние три идеи уже были даны (boohoo), но я поместил их здесь для потомков. Я ДУМАЛ о них без обмана. : -p
Вычислите, есть ли у B совпадение, затем предоставьте дополнительную UNIONed строку для набора B, чтобы предоставить NULL, когда нет совпадения.
SELECT A.Id, A.Something, B.Id, B.Whatever, B.SomethingElse
FROM
(
SELECT
A.*,
CASE
WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN 1
ELSE 0
END Which
FROM A
) A
INNER JOIN (
SELECT 1 Which, B.* FROM B
UNION ALL SELECT 0, B* FROM B WHERE 1 = 0
) B ON A.Which = B.Which
AND (
A.Which = 0
OR (
A.Which = 1
AND A.Id = b.Id
)
)
Немного другой взгляд на тот же запрос:
SELECT A.Id, B.Id
FROM
(
SELECT
A.*,
CASE
WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN A.Id
ELSE -1 // a value that doesn't exist in B
END PseudoId
FROM A
) A
INNER JOIN (
SELECT B.Id PseudoId, B.Id FROM B
UNION ALL SELECT -1, NULL
) B ON A.Which = B.Which
AND A.PseudoId = B.PseudoId
Только для SQL Server специально. Я знаю, это действительно левое соединение, но это не говорит LEFT
там!
SELECT A.Id, B.Id
FROM
A
OUTER APPLY (
SELECT *
FROM B
WHERE A.Id = B.Id
) B
Получите внутреннее соединение, затем СОЕДИНИТЕ внешнее соединение:
SELECT A.Id, B.Id
FROM
A
INNER JOIN B ON A.name = B.name
UNION ALL
SELECT A.Id, NULL
FROM A
WHERE NOT EXISTS (
SELECT *
FROM B
WHERE A.Id = B.Id
)
Используйте ПРАВИЛЬНОЕ СОЕДИНЕНИЕ. Это не левое соединение!
SELECT A.Id, B.Id
FROM
B
RIGHT JOIN A ON B.name = A.name
Просто выберите значение B в выражении подзапроса (пусть будет только один B на A). Несколько столбцов из B могут быть их собственными выражениями (YUCKO!):
SELECT A.Id, (SELECT TOP 1 B.Id FROM B WHERE A.Id = B.Id) Bid
FROM A
Любой, кто использует Oracle, может нуждаться в некоторых предложениях FROM DUAL
в любых SELECT, которые не имеют FROM.
вы можете использовать оператор oracle + для левого соединения: -
SELECT A.id, B.id ОТ А, В ON A.name = B.name(+)
Найти ссылку: -
SELECT A.id, B.id
FROM A full outer join B
ON A.name = B.name
where A.name is not null
Я не уверен, что вы просто не можете использовать LEFT JOIN
, или если вам вообще запрещено использовать любой JOINS
. Но насколько я понимаю ваши требования, INNER JOIN
должен работать:
SELECT A.id, B.id
FROM A
INNER JOIN B ON A.name = B.name
Имитация левого соединения с использованием чистого простого SQL:
SELECT A.name
FROM A
where (select count(B.name) from B where A.id = B.id)<1;
В левом соединении нет строк в B, ссылающихся на A, поэтому 0 имен в B будут ссылаться на строки в A, у которых нет соответствия + или A.id = B.id в предложении where для имитации внутреннего соединения