осталось присоединиться, вернувшись больше, чем ожидалось - PullRequest
7 голосов
/ 10 октября 2011

Используя следующий запрос

select *
from table1
left join table2 on table1.name = table2.name

table1 возвращает 16 строк, а table2 возвращает 35 строк.

Я ожидал, что вышеуказанный запрос вернет 16 строк из-за left join, но он возвращает 35 строк. right join также возвращает 35 строк

Почему это происходит и как заставить его вернуть 16 строк?

Ответы [ 6 ]

13 голосов
/ 10 октября 2011

LEFT JOIN может возвращать несколько копий данных из таблицы1, если на внешний ключ для строки в таблице 1 ссылаются несколько строк в таблице 2.

Если вы хотите, чтобы он возвращал только 16 строк, по одной для каждой строки таблицы 1, и со случайным набором данных для таблицы 2, вы можете использовать просто обычную GROUP BY:

select *
from table1
left join table2 on table1.name = table2.name
group by table1.name

GROUP BY агрегирует строки на основе поля, поэтому все дубликаты таблицы 1 будут объединены в одну строку. Как правило, вы указываете агрегатные функции, чтобы объяснить, как строки должны свернуться (например, для строки чисел вы можете свернуть ее с помощью SUM (), чтобы одна строка была итоговой). Если вам нужна только одна случайная строка, не указывайте никаких агрегатных функций. MySQL по умолчанию просто выберет одну строку (обратите внимание, что это специфично для MySQL, большинство баз данных потребует, чтобы вы указывали агрегаты при группировании). То, как оно выбирается, не является технически «случайным», но оно не обязательно предсказуемо для вас. Я думаю, под «случайным» вы на самом деле подразумеваете «подойдет любая строка».

4 голосов
/ 10 октября 2011

Предположим, у вас есть следующие таблицы:

tbl1:
|Name |
-------
|Name1|
|Name2|

tbl2:
|Name |Value |
--------------
|Name1|Value1|
|Name1|Value2|
|Name3|Value1|

За ЛЕВОЕ СОЕДИНЕНИЕ вы получите:

|tbl1.Name|tbl2.Name|Value |
----------------------------
|Name1    | Name1   |Value1|
|Name1    | Name1   |Value2|
|Name2    | NULL    | NULL |

Итак, LEFT JOIN означает, что все записи из LEFT (первой) таблицы будут возвращены независимо от их присутствия в правой таблице.

Для вашего вопроса вам нужно указать некоторые конкретные поля вместо использования "*" и добавить GROUP BY tbl1.Name - так ваш запрос будет выглядеть как

select tbl1.Name, SOME_AGGREGATE_FUNCTION(tbl2.specific_field), ...
from table1
left join table2 on table1.name = table2.name
GROUP BY tbl1.Name
1 голос
/ 21 марта 2018

Один из способов использовать это - использовать мощь SQL.

select distinct tbl1.id, *
from table1 tbl1
left join table2 tbl2 on tbl2.name = tbl1.name

where
 ....................

Обратите внимание, что я также использую псевдоним.

0 голосов
/ 10 июня 2019

Дублирование может быть причиной. Смотрите пример в посте
https://alexpetralia.com/posts/2017/7/19/more-dangerous-subtleties-of-joins-in-sql

0 голосов
/ 10 октября 2011

В соответствии с вашим комментарием «Случайная строка из таблицы2, если имя из таблицы1 совпадает с именем из таблицы2», вы можете использовать следующее:

select table1.name, (select top 1 somecolumn from table2 where table2.name = table1.name)
from table1

Обратите внимание, что top 1 - это не mysql, адля SQL Server

0 голосов
/ 10 октября 2011

Если столбец имени не является уникальным в таблицах, возможно, у вас просто есть дубликаты в таблице 2.

Попробуйте выполнить:

select * from table2 where name not in (select name from table1);

Если вы не получили результатов назад, дубликаты наИмя столбца является причиной возвращения лишних строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...