SQL | Соединение (внутреннее, левое, правое и полное соединение)
Оператор SQL Join используется для объединения данных или строк из двух или более таблиц на основе общего поля между ними. Существуют следующие типы соединений:
- ВНУТРЕННЕЕ СОЕДИНЕНИЕ
- ЛЕВОЕ СОЕДИНЕНИЕ
- ПРАВОЕ СОЕДИНЕНИЕ
- ПОЛНОЕ СОЕДИНЕНИЕ
- ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ
Студент
СтудентКурс
Самым простым соединением является ВНУТРЕННЕЕ СОЕДИНЕНИЕ.
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;
Выход:
ИМЯ | COURSE_ID |
---|---|
9000 2 ЖЕСТКИЙ | 1 |
PRATIK | 2 |
2 | |
DEEP | 3 |
SAPTARHI | 90 183|
ДХАНРАДЖ | НУЛЬ |
РОХИТ | НУЛЬ 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 |
Департамент | |
---|---|
Dept_id | 90 171 Название отдела|
10 | IT |
30 | HR | 9017 9
40 | TIS |
Запрос: найти всех сотрудников и их соответствующие отделы.
Решение: (Сотрудник) ⋈ (Отдел)
Emp_id | Emp_name | Dept_id | Dept_id | Dept_name |
---|---|---|---|---|
1 | Ram | 90 171 1010 | 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
Есть две проблемы с вашим запросом:
- Каждой таблице и подзапросу нужно имя, поэтому вы должны назвать подзапрос
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ...) КАК ВКЛ...
. - Подзапрос в том виде, в каком он у вас есть, возвращает только один период строки, но на самом деле вам нужна одна строка для каждого пользователя . Для этого вам нужен один запрос, чтобы получить максимальную дату, а затем самостоятельно присоединиться, чтобы получить всю строку.
Предполагая, что ничьих для платежей нет. 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.