SQL | Соединение (внутреннее, левое, правое и полное соединение)

Оператор SQL Join используется для объединения данных или строк из двух или более таблиц на основе общего поля между ними. Существуют следующие типы соединений:

  • ВНУТРЕННЕЕ СОЕДИНЕНИЕ
  • ЛЕВОЕ СОЕДИНЕНИЕ
  • ПРАВОЕ СОЕДИНЕНИЕ
  • ПОЛНОЕ СОЕДИНЕНИЕ
  • ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ
9000 2 Рассмотрим две приведенные ниже таблицы следующим образом: 

Студент

 

СтудентКурс  

Самым простым соединением является ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

A. INNER JOIN

Ключевое слово INNER JOIN выбирает все строки из обеих таблиц, если выполняется условие. Это ключевое слово создаст набор результатов, объединив все строки из обеих таблиц, где выполняется условие, т. е. значение общего поля будет одинаковым.

Синтаксис

 SELECT table1. column1,table1.column2,table2.column1,....
ИЗ таблицы1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ таблица2
ON table1.matching_column = table2.matching_column;
  таблица1  : Первая таблица.
  таблица2  : Вторая таблица
  match_column  : Столбец, общий для обеих таблиц. 

Примечание : Мы также можем написать JOIN вместо INNER JOIN. СОЕДИНЕНИЕ такое же, как ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Примеры запросов (INNER JOIN)

Этот запрос покажет имена и возраст студентов, зачисленных на разные курсы.

 ВЫБЕРИТЕ StudentCourse.COURSE_ID, Student.NAME, Student.AGE FROM Student
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
ON Student.ROLL_NO = StudentCourse.ROLL_NO; 

Вывод :  

B. LEFT JOIN

Это объединение возвращает все строки таблицы с левой стороны объединения и сопоставляет строки таблицы с правой стороны объединения. Для строк, для которых нет соответствующей строки справа, набор результатов будет содержать null . ЛЕВОЕ СОЕДИНЕНИЕ также известно как ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ.

Синтаксис:  

 SELECT table1.column1,table1.column2,table2.column1,....
ИЗ таблицы1
ЛЕВОЕ СОЕДИНЕНИЕ таблица2
ON table1.matching_column = table2.matching_column;
таблица1: первая таблица.
таблица2: вторая таблица
Matching_column: столбец, общий для обеих таблиц. 

Примечание : Мы также можем использовать ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ вместо ЛЕВОГО СОЕДИНЕНИЯ, оба одинаковы.

Примеры запросов (LEFT JOIN)

 SELECT Student.NAME,StudentCourse.COURSE_ID
ОТ Студент
LEFT JOIN
ON StudentCourse.ROLL_NO = Student.ROLL_NO; 

Выход

C. ПРАВОЕ СОЕДИНЕНИЕ

ПРАВОЕ СОЕДИНЕНИЕ аналогично ЛЕВОМУ СОЕДИНЕНИЮ. Это объединение возвращает все строки таблицы с правой стороны объединения и совпадающие строки для таблицы с левой стороны объединения.

Для строк, для которых нет соответствующей строки слева, набор результатов будет содержать ноль . ПРАВОЕ СОЕДИНЕНИЕ также известно как ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ.

Синтаксис:  

 SELECT table1.column1,table1.column2,table2.column1,....
ИЗ таблицы1
ПРАВОЕ СОЕДИНЕНИЕ таблица2
ON table1.matching_column = table2.matching_column;
таблица1: первая таблица.
таблица2: вторая таблица
Matching_column: столбец, общий для обеих таблиц. 

Примечание : мы также можем использовать RIGHT OUTER JOIN вместо RIGHT JOIN, оба они одинаковы.

 

Примеры запросов (ПРАВОЕ СОЕДИНЕНИЕ) :

 ВЫБЕРИТЕ Student.NAME,StudentCourse.COURSE_ID
ОТ Студент
ПРАВО ПРИСОЕДИНЯЙСЯ
ON StudentCourse.ROLL_NO = Student.ROLL_NO; 

Выходные данные:  

D. ПОЛНОЕ СОЕДИНЕНИЕ

ПОЛНОЕ СОЕДИНЕНИЕ создает результирующий набор, объединяя результаты ЛЕВОГО СОЕДИНЕНИЯ и ПРАВОГО СОЕДИНЕНИЯ. Набор результатов будет содержать все строки из обеих таблиц. Для строк, для которых нет соответствия, набор результатов будет содержать NULL значений.

Синтаксис:   

 SELECT table1.column1,table1.column2,table2.column1,....
ИЗ таблицы1
ПОЛНОЕ СОЕДИНЕНИЕ таблица2
ON table1.matching_column = table2.matching_column;
таблица1: первая таблица.
таблица2: вторая таблица
Matching_column: столбец, общий для обеих таблиц. 

Примеры запросов (FULL JOIN)

 SELECT Student.NAME,StudentCourse.COURSE_ID
ОТ Студент
ПОЛНОЕ СОЕДИНЕНИЕ
ON StudentCourse.ROLL_NO = Student.ROLL_NO; 

Выход:   

90 183

РИЯНКА

90 183

1

ИМЯ

COURSE_ID

9000 2 ЖЕСТКИЙ

1

PRATIK

2

2

DEEP

3

SAPTARHI

ДХАНРАДЖ

НУЛЬ

РОХИТ

НУЛЬ 900 05

NIRAJ

NULL

NULL

9000 2 4

NULL

5

NULL

4

Левое соединение (видео)
Правое СОЕДИНЕНИЕ (видео)
Полное СОЕДИНЕНИЕ (видео)
SQL | JOIN (декартово соединение, самосоединение) 

E.

Естественное соединение (⋈)

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

Обе таблицы должны иметь в списке один общий столбец с одинаковым именем столбца и одним и тем же типом данных.

Две таблицы соединены с помощью перекрестного соединения.

СУБД будет искать общий столбец с таким же именем и типом данных. В результате сохраняются кортежи, имеющие точно такие же значения в общих столбцах.

Пример:

Сотрудник

Emp_id Emp_name Dept_id 901 74
1 Рэм 10
2 Джон 30 901 74
3 Боб 50
90 171 Название отдела 9017 9

Департамент

Dept_id
10 IT
30 HR
40 TIS

Запрос: найти всех сотрудников и их соответствующие отделы.

Решение: (Сотрудник) ⋈ (Отдел)

90 171 10
Emp_id Emp_name Dept_id Dept_id Dept_name
1 Ram 10 IT 
2 Джон 30 30 час
Данные сотрудников Данные отдела

Эта статья предоставлена ​​ Harsh Agarwal . Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью с помощью write.geeksforgeeks.org или отправить ее по адресу [email protected]. Посмотрите, как ваша статья появится на главной странице GeeksforGeeks, и помогите другим гикам.

Пожалуйста, пишите в комментариях, если вы обнаружите что-то неправильное или если вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.


sql — ВНУТРЕННЕЕ СОЕДИНЕНИЕ MySQL выбирает только одну строку из второй таблицы

спросил

Изменено 2 месяца назад

Просмотрено 299к раз

У меня есть таблица пользователей и таблица платежей , для каждого пользователя, у которых есть платежи, может быть несколько связанных платежей в таблице платежей . Я хотел бы выбрать всех пользователей, у которых есть платежи, но выбрать только их последний платеж. Я пробую этот SQL, но я никогда раньше не пробовал вложенные операторы SQL, поэтому я хочу знать, что я делаю неправильно. Благодарим за помощь

 SELECT u.*
ОТ пользователей AS u
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБЕРИТЕ стр.*
        ОТ платежей AS p
        ЗАКАЗАТЬ ПО дате DESC
        ПРЕДЕЛ 1
    )
    ВКЛ p.user_id = u.id
ГДЕ u.package = 1
 
  • mysql
  • sql
  • select
  • внутреннее соединение

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

 ВЫБОР u.*, стр.*
ОТ пользователей u
    INNER JOIN платежи p
        ВКЛ u.id = p.user_ID
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ
    (
        ВЫБЕРИТЕ user_ID, MAX(дата) maxDate
        ОТ платежей
        СГРУППИРОВАТЬ ПО user_ID
    ) b ON p.user_ID = b.user_ID И
            p.date = b.maxDate
ГДЕ u.package = 1
 

10

 ВЫБОР u. *, стр.*
ОТ пользователей AS u
INNER JOIN платежи AS p ON p.id = (
    ВЫБЕРИТЕ идентификатор
    ОТ платежей AS p2
    ГДЕ p2.user_id = u.id
    ЗАКАЗАТЬ ПО дате DESC
    ПРЕДЕЛ 1
)
 

Или

 ВЫБЕРИТЕ u.*, p.*
ОТ пользователей AS u
INNER JOIN платежи AS p ON p.user_id = u.id
ГДЕ НЕ СУЩЕСТВУЕТ(
    ВЫБЕРИТЕ 1
    ОТ платежей AS p2
    ГДЕ
        p2.user_id = p.user_id И
        (p2.date >
p.date ИЛИ (p2.date = p.date И p2.id > p.id)) )

Эти решения лучше, чем принятый ответ, потому что они работают правильно, когда есть несколько платежей с одним и тем же пользователем и датой. Вы можете попробовать SQL Fiddle.

4

 ВЫБРАТЬ u.*, p.*, max(p.date)
ОТ платежей р
ПРИСОЕДИНЯЙТЕСЬ к пользователям u ON u.id=p.user_id AND u.package = 1
СГРУППИРОВАТЬ ПО u.id
ЗАКАЗАТЬ ПО п.дате DESC
 

Проверьте этот sqlfiddle

3

 ВЫБЕРИТЕ u.
* ОТ пользователей AS u ВНУТРЕННЕЕ СОЕДИНЕНИЕ ( ВЫБЕРИТЕ стр.*, @num := if(@id = user_id, @num + 1, 1) как row_number, @id := user_id как tmp ОТ платежей AS p, (ВЫБЕРИТЕ @num := 0) х, (ВЫБЕРИТЕ @id := 0) у ЗАКАЗАТЬ ПО p.user_id ASC, дата DESC) ВКЛ (p.user_id = u.id) и (p.row_number=1) ГДЕ u.package = 1

0

Вы можете попробовать это:

 SELECT u.*, p.*
ОТ пользователей AS u LEFT JOIN (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY userid ORDER BY [Date] DESC) AS RowNo
    ОТ платежей
) AS p ON u.userid = p.userid И p.RowNo=1
 

1

Есть две проблемы с вашим запросом:

  1. Каждой таблице и подзапросу нужно имя, поэтому вы должны назвать подзапрос ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ...) КАК ВКЛ... .
  2. Подзапрос в том виде, в каком он у вас есть, возвращает только один период строки, но на самом деле вам нужна одна строка для каждого пользователя . Для этого вам нужен один запрос, чтобы получить максимальную дату, а затем самостоятельно присоединиться, чтобы получить всю строку.

Предполагая, что ничьих для платежей нет. date , попробуйте:

 SELECT u.*, p.*
    ОТ (
        ВЫБЕРИТЕ МАКС(p.date) КАК дату, p.user_id
        ОТ платежей AS p
        СГРУППИРОВАТЬ ПО p.user_id
    ) КАК последнийP
    INNER JOIN пользователей AS u ON lastP.user_id = u.id
    INNER JOIN платежи AS p ON p.user_id = u.id AND p.date = lastP.date
    ГДЕ u.package = 1
 

2

Ответ @John Woo помог мне решить аналогичную проблему. Я улучшил его ответ, установив правильный порядок. Это сработало для меня:

 SELECT a.*, c.*
ОТ пользователей
    INNER JOIN платежи c
        ПО a. id = c.user_ID
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБЕРИТЕ user_ID, MAX (дата) как maxDate FROM
        (
            ВЫБЕРИТЕ user_ID, дату
            ОТ платежей
            ЗАКАЗАТЬ ПО дате DESC
        ) д
        СГРУППИРОВАТЬ ПО user_ID
    ) b ON c.user_ID = b.user_ID И
           c.date = b.maxDate
ГДЕ a.package = 1
 

Однако я не уверен, насколько это эффективно.

 ВЫБРАТЬ U.*, V.* ОТ пользователей КАК U
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ *
ОТ платежей
ГДЕ id В (
ВЫБЕРИТЕ МАКС(ИД)
ОТ платежей
СГРУППИРОВАТЬ ПО user_id
)) AS V ON U.id = V.user_id
 

Это заставит его работать

Матей Михай дал простое и эффективное решение, но оно не будет работать, пока не поместите MAX (дата) в часть SELECT, поэтому этот запрос станет:

 SELECT u.*, p.* , макс(дата)
ОТ платежей р
ПРИСОЕДИНЯЙТЕСЬ к пользователям u ON u.id=p.user_id AND u.package = 1
СГРУППИРОВАТЬ ПО u.id
 

Упорядочить по не имеет значения при группировке, но может упорядочить окончательный результат, предоставленный группировкой по. Я попробовал это, и это сработало для меня.

Мой ответ, вдохновленный @valex, очень полезен, если вам нужно несколько столбцов в предложении ORDER BY.

 ВЫБЕРИТЕ u.*
    ОТ пользователей AS u
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБЕРИТЕ стр.*,
         @num := if(@id = user_id, @num + 1, 1) как row_number,
         @id := user_id как tmp
        ОТ (ВЫБРАТЬ * ОТ платежей ORDER BY p.user_id ASC, дата DESC) AS p,
             (ВЫБЕРИТЕ @num := 0) х,
             (ВЫБЕРИТЕ @id := 0) у
        )
    ВКЛ (p.user_id = u.id) и (p.row_number=1)
    ГДЕ u.package = 1
 

Это довольно просто сделать внутреннее соединение, а затем сгруппировать по user_id и использовать максимальную агрегатную функцию в payment_id, предполагая, что ваша таблица является пользовательской, а платежный запрос может быть

 SELECT user.id, max(payment.id)
ОТ ВНУТРЕННЕГО ПРИСОЕДИНЕНИЯ пользователя к оплате (user.id = payment.user_id)
СГРУППИРОВАТЬ ПО user.id
 

Если вам не нужно возвращать платеж из запроса, вы можете сделать это с отличным , например:

 SELECT DISTINCT u.