Перейти к содержимому

Как джойнить таблицу саму на себя

  • автор:

Понимание джойнов сломано. Это точно не пересечение кругов, честно

Так получилось, что я провожу довольно много собеседований на должность веб-программиста. Один из обязательных вопросов, который я задаю — это чем отличается INNER JOIN от LEFT JOIN.

Чаще всего ответ примерно такой: «inner join — это как бы пересечение множеств, т.е. остается только то, что есть в обеих таблицах, а left join — это когда левая таблица остается без изменений, а от правой добавляется пересечение множеств. Для всех остальных строк добавляется null». Еще, бывает, рисуют пересекающиеся круги.

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

Дело в том, что этот ответ в общем случае неверен. Ну или, как минимум, не точен.

Давайте рассмотрим почему, и заодно затронем еще парочку тонкостей join-ов.

Во-первых, таблица — это вообще не множество. По математическому определению, во множестве все элементы уникальны, не повторяются, а в таблицах в общем случае это вообще-то не так. Вторая беда, что термин «пересечение» только путает.

(Update. В комментах идут жаркие споры о теории множеств и уникальности. Очень интересно, много нового узнал, спасибо)

INNER JOIN

Давайте сразу пример.

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

INSERT INTO table1 (id) VALUES (1), (1) (3); INSERT INTO table2 (id) VALUES (1), (1), (2);

Давайте, их, что ли, поджойним

SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id;

Если бы это было «пересечение множеств», или хотя бы «пересечение таблиц», то мы бы увидели две строки с единицами.

На практике ответ будет такой:

| id | id | | --- | --- | | 1 | 1 | | 1 | 1 | | 1 | 1 | | 1 | 1 |

Для начала рассмотрим, что такое CROSS JOIN. Вдруг кто-то не в курсе.

CROSS JOIN — это просто все возможные комбинации соединения строк двух таблиц. Например, есть две таблицы, в одной из них 3 строки, в другой — 2:

select * from t1;
id ---- 1 2 3
select * from t2;
id ---- 4 5

Тогда CROSS JOIN будет порождать 6 строк.

select * from t1 cross join t2; 
id | id ----+---- 1 | 4 1 | 5 2 | 4 2 | 5 3 | 4 3 | 5

Так вот, вернемся к нашим баранам.
Конструкция

t1 INNER JOIN t2 ON condition

— это, можно сказать, всего лишь синтаксический сахар к

t1 CROSS JOIN t2 WHERE condition

Т.е. по сути INNER JOIN — это все комбинации соединений строк с неким фильтром condition . В общем-то, можно это представлять по разному, кому как удобнее, но точно не как пересечение каких-то там кругов.

Небольшой disclaimer: хотя inner join логически эквивалентен cross join с фильтром, это не значит, что база будет делать именно так, в тупую: генерить все комбинации и фильтровать. На самом деле там более интересные алгоритмы.

LEFT JOIN

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

Опять же, создадим две таблицы:

insert into t1 (id) values (1), (1), (3); insert into t2 (id) values (1), (1), (4), (5);

Теперь сделаем LEFT JOIN:

SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id;

Результат будет содержать 5 строк, а не по количеству строк в левой таблице, как думают очень многие.

| id | id | | --- | --- | | 1 | 1 | | 1 | 1 | | 1 | 1 | | 1 | 1 | | 3 | |

Так что, LEFT JOIN — это тоже самое что и INNER JOIN (т.е. все комбинации соединений строк, отфильтрованных по какому-то условию), и плюс еще записи из левой таблицы, для которых в правой по этому фильтру ничего не совпало.

LEFT JOIN можно переформулировать так:

SELECT * FROM t1 CROSS JOIN t2 WHERE t1.id = t2.id UNION ALL SELECT t1.id, null FROM t1 WHERE NOT EXISTS ( SELECT FROM t2 WHERE t2.id = t1.id )

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

Условие ON

Удивительно, но по моим ощущениям 99% разработчиков считают, что в условии ON должен быть id из одной таблицы и id из второй. На самом деле там любое булево выражение.

Например, есть таблица со статистикой юзеров users_stats, и таблица с ip адресами городов.
Тогда к статистике можно прибавить город

SELECT s.id, c.city FROM users_stats AS s JOIN cities_ip_ranges AS c ON c.ip_range && s.ip

где && — оператор пересечения (см. расширение посгреса ip4r)

Если в условии ON поставить true, то это будет полный аналог CROSS JOIN

"table1 JOIN table2 ON true" == "table1 CROSS JOIN table2"

Производительность

Есть люди, которые боятся join-ов как огня. Потому что «они тормозят». Знаю таких, где есть полный запрет join-ов по проекту. Т.е. люди скачивают две-три таблицы себе в код и джойнят вручную в каком-нибудь php.

Это, прямо скажем, странно.

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

Сложность этой задачи O(n!), где n — количество объединяемых таблиц. Поэтому для большого количества таблиц, потратив некоторое время на поиски оптимальной последовательности, планировщик прекращает эти поиски и делает такой план, какой успел придумать. В этом случае иногда бывает выгодно вынести часть запроса в подзапрос CTE; например, если вы точно знаете, что, поджойнив две таблицы, мы получим очень мало записей, и остальные джойны будут стоить копейки.

Кстати, Еще маленький совет по производительности. Если нужно просто найти элементы в таблице, которых нет в другой таблице, то лучше использовать не ‘LEFT JOIN… WHERE… IS NULL’, а конструкцию EXISTS. Это и читабельнее, и быстрее.

Выводы

Как мне кажется, не стоит использовать диаграммы Венна для объяснения джойнов. Также, похоже, нужно избегать термина «пересечение».

Как объяснить на картинке джойны корректно, я, честно говоря, не представляю. Если вы знаете — расскажите, плиз, и киньте в коменты.

Update В этом видео я наглядно объясняю, как правильно визуализировать джойны (English):

Update2 Продолжение статьи здесь: https://habr.com/ru/post/450528/

Больше полезного можно найти на telegram-канале о разработке «Cross Join», где мы обсуждаем базы данных, языки программирования и всё на свете!

Соединение таблиц – операция JOIN и ее виды

Говоря про соединение таблиц в SQL, обычно подразумевают один из видов операции JOIN. Не стоит путать с объединением таблиц через операцию UNION. В этой статье я постараюсь простыми словами рассказать именно про соединение, чтобы после ее прочтения Вы могли использовать джойны в работе и не допускать грубых ошибок.

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

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

Таблица «Сотрудники», содержит поля:

  • id – идентификатор сотрудника
  • Имя
  • Отдел – идентификатор отдела, в котором работает сотрудник
id Имя Отдел
1 Юлия 1
2 Федор 2
3 Алексей NULL
4 Светлана 2

Таблица «Отделы», содержит поля:

  • id – идентификатор отдела
  • Наименование
id Наименование
1 Кухня
2 Бар
3 Администрация

Давайте уже быстрее что-нибудь покодим.

INNER JOIN

Самый простой вид соединения INNER JOIN – внутреннее соединение. Этот вид джойна выведет только те строки, если условие соединения выполняется (является истинным, т.е. TRUE). В запросах необязательно прописывать INNER – если написать только JOIN, то СУБД по умолчанию выполнить именно внутреннее соединение.

Давайте соединим таблицы из нашего примера, чтобы ответить на вопрос, в каких отделах работают сотрудники (читайте комментарии в запросе для понимания синтаксиса).

SELECT -- Перечисляем столбцы, которые хотим вывести Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел -- выводим наименование отдела и переименовываем столбец через as FROM -- таблицы для соединения перечисляем в предложении from Сотрудники -- обратите внимание, что мы не указали вид соединения, поэтому выполнится внутренний (inner) джойн JOIN Отделы -- условия соединения прописываются после ON -- условий может быть несколько, записанных через and, or и т.п. ON Сотрудники.Отдел = Отделы.id

Получим следующий результат:

id Имя Отдел
1 Юлия Кухня
2 Федор Бар
4 Светлана Бар

Из результатов пропал сотрудник Алексей (id = 3), потому что условие «Сотрудники.Отдел = Отделы.id» не будет истинно для этой сроки из таблицы «Сотрудники» с каждой строкой из таблицы «Отделы». По той же логике в результате нет отдела «Администрация». Попробую это визуализировать (зеленные линии – условие TRUE, иначе линия красная):

Визуализация inner join

Если не углубляться в то, как внутреннее соединение работает под капотом СУБД, то происходит примерно следующее:

  • Каждая строка из одной таблицы сравнивается с каждой строкой из другой таблицы
  • Строка возвращается, если условие сравнения является истинным

Если для одной или нескольких срок из левой таблицы (в рассмотренном примере левой таблицей является «Сотрудники», а правой «Отделы») истинным условием соединения будут являться одна или несколько срок из правой таблицы, то строки умножат друг друга (повторятся). В нашем примере так произошло для отдела с поэтому строка из таблицы «Отделы» повторилась дважды для Федора и Светланы.
Перемножение таблиц проще ощутить на таком примере, где условие соединения будет всегда возвращать TRUE, например 1=1:

SELECT * FROM Сотрудники JOIN Отделы ON 1=1

В результате получится 12 строк (4 сотрудника * 3 отдела), где для каждого сотрудника подтянется каждый отдел.

Также хочу сразу отметить, что в соединении может участвовать сколько угодно таблиц, можно таблицу соединить даже саму с собой (в аналитических задачах это не редкость). Какая из таблиц будет правой или левой не имеется значения для INNER JOIN (для внешних соединений типа LEFT JOIN или RIGHT JOIN это важно. Читайте далее). Пример соединения 4-х таблиц:

SELECT * FROM Table_1 JOIN Table_2 ON Table_1.Column_1 = Table_2.Column_1 JOIN Table_3 ON Table_1.Column_1 = Table_3.Column_1 AND Table_2.Column_1 = Table_3.Column_1 JOIN Table_1 AS Tbl_1 -- Задаем алиас для таблицы, чтобы избежать неоднозначности -- Если в Table_1.Column_1 хранится порядковый номер какого-то объекта, -- то так можно присоединить следующий по порядку объект ON Table_1.Column_1 = Tbl_1.Column_1 + 1

Как видите, все просто, прописываем новый джойн после завершения условий предыдущего соединения. Обратите внимание, что для Table_3 указано несколько условий соединения с двумя разными таблицами, а также Table_1 соединяется сама с собой по условию с использованием сложения.
Строки, которые выведутся запросом, должны совпасть по всем условиям. Например:

  • Строка из Table_1 соединилась со строкой из Table_2 по условию первого JOIN. Давайте назовем ее «объединенной строкой» из двух таблиц;
  • Объединенная строка успешно соединилась с Table_3 по условию второго JOIN и теперь состоит из трех таблиц;
  • Для объединенной строки не нашлось строки из Table_1 по условию третьего JOIN, поэтому она не выводится вообще.

На этом про внутреннее соединение и логику соединения таблиц в SQL – всё. Если остались неясности, то спрашивайте в комментариях.
Далее рассмотрим отличия остальных видов джойнов.

LEFT JOIN и RIGHT JOIN

Левое и правое соединения еще называют внешними. Главное их отличие от внутреннего соединения в том, что строка из левой (для LEFT JOIN) или из правой таблицы (для RIGHT JOIN) попадет в результаты в любом случае. Давайте до конца определимся с тем, какая таблица левая, а какая правая.
Левая таблица та, которая идет перед написанием ключевых слов [LEFT | RIGHT| INNER] JOIN, правая таблица – после них:

SELECT * FROM Левая_таблица AS lt LEFT JOIN Правая_таблица AS rt ON lt.c = rt.c

Теперь изменим наш SQL-запрос из самого первого примера так, чтобы ответить на вопрос «В каких отделах работают сотрудники, а также показать тех, кто не распределен ни в один отдел?»:

SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники LEFT JOIN Отделы -- добавляем только left ON Сотрудники.Отдел = Отделы.id

Результат запроса будет следующим:

id Имя Отдел
1 Юлия Кухня
2 Федор Бар
3 Алексей NULL
4 Светлана Бар

Как видите, запрос вернул все строки из левой таблицы «Сотрудники», дополнив их значениями из правой таблицы «Отделы». А вот строка для отдела «Администрация» не показана, т.к. для нее не нашлось совпадений слева.

Это мы рассмотрели пример для левого внешнего соединения. Для RIGHT JOIN будет все тоже самое, только вернутся все строки из таблицы «Отделы»:

id Имя Отдел
1 Юлия Кухня
2 Федор Бар
4 Светлана Бар
NULL NULL Администрация

Алексей «потерялся», Администрация «нашлась».

Вопрос для Вас. Что надо изменить в последнем приведенном SQL-запросе, чтобы результат остался тем же, но вместо LEFT JOIN, использовался RIGHT JOIN?

Ответ. Нужно поменять таблицы местами:

SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Отделы RIGHT JOIN Сотрудники ON Сотрудники.Отдел = Отделы.id

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

FULL JOIN

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

Давайте посмотрим всех сотрудников и все отделы из наших тестовых таблиц:

SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники FULL JOIN Отделы ON Сотрудники.Отдел = Отделы.id
id Имя Отдел
1 Юлия Кухня
2 Федор Бар
3 Алексей NULL
4 Светлана Бар
NULL NULL Администрация

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

Вместо заключения

Помните о порядке выполнения соединений и порядке таблиц, если используете несколько соединений и используете внешние соединения. Можно выполнять LEFT JOIN для сохранения всех строк из самой первой таблицы, а последним внутренним соединением потерять часть данных. На маленьких таблицах косяк заметить легко, на огромных очень тяжело, поэтому будьте внимательны.
Рассмотрим последний пример и введем еще одну таблицу «Банки», в которой обслуживаются наши придуманные сотрудники:

id Наименование
1 Банк №1
2 Лучший банк
3 Банк Лидер

В таблицу «Сотрудники» добавим столбец «Банк»:

id Имя Отдел Банк
1 Юлия 1 2
2 Федор 2 2
3 Алексей NULL 3
4 Светлана 2 4

Теперь выполним такой запрос:

SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел, Банки.Наименование AS Банк FROM Сотрудники LEFT JOIN Отделы ON Сотрудники.Отдел = Отделы.id INNER JOIN Банки ON Сотрудники.Банк = Банки.id

В результате потеряли информацию о Светлане, т.к. для нее не нашлось банка с (такое происходит из-за неправильной проектировки БД):

id Имя Отдел Банк
1 Юлия Кухня Лучший банк
2 Федор Бар Лучший банк
3 Алексей NULL Банк Лидер

Хочу обратить внимание на то, что любое сравнение с неизвестным значением никогда не будет истинным (даже NULL = NULL). Эту грубую ошибку часто допускают начинающие специалисты. Подробнее читайте в статье про значение NULL в SQL.

Пройдите мой тест на знание основ SQL. В нем есть задания на соединения таблиц, которые помогут закрепить материал.

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

Если какие нюансы джойнов остались не раскрытыми, или что-то описано не совсем понятно, что-то надо дополнить, то пишите в комментариях. Буду только рад вопросам и предложениям.

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

-- Создаем CTE для таблиц из примеров WITH Сотрудники AS( SELECT 1 AS id, 'Юлия' AS Имя, 1 AS Отдел, 2 AS Банк UNION ALL SELECT 2, 'Федор', 2, 2 UNION ALL SELECT 3, 'Алексей', NULL, 3 UNION ALL SELECT 4, 'Светлана', 2, 4 ), Отделы AS( SELECT 1 AS id, 'Кухня' AS Наименование UNION ALL SELECT 2, 'Бар' UNION ALL SELECT 3, 'Администрация' ), Банки AS( SELECT 1 AS id, 'Банк №1' AS Наименование UNION ALL SELECT 2, 'Лучший банк' UNION ALL SELECT 3, 'Банк Лидер' ) -- Если надо выполнить другие запросы, то сначала закоментируй это запрос с помощью /**/, -- а нужный запрос расскоментируй или напиши свой. -- Это пример внутреннего соединения SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники JOIN Отделы ON Сотрудники.Отдел = Отделы.id /* -- Пример левого джойна SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники LEFT JOIN Отделы ON Сотрудники.Отдел = Отделы.id */ /* -- Результат этого запроса будет аналогичен результату запроса выше, хотя соединение отличается SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Отделы RIGHT JOIN Сотрудники ON Сотрудники.Отдел = Отделы.id */ /* -- Правое соединение SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники RIGHT JOIN Отделы ON Сотрудники.Отдел = Отделы.id */ /* -- Пример с использованием разных видов JOIN SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Отделы RIGHT JOIN Сотрудники ON Сотрудники.Отдел = Отделы.id LEFT JOIN Банки ON Банки.id = Сотрудники.Банк */ /* -- Полное внешние соединение SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел FROM Сотрудники FULL JOIN Отделы ON Сотрудники.Отдел = Отделы.id */ /* -- Пример с потерей строки из-за последнего внутреннего соединения SELECT Сотрудники.id, Сотрудники.Имя, Отделы.Наименование AS Отдел, Банки.Наименование AS Банк FROM Сотрудники LEFT JOIN Отделы ON Сотрудники.Отдел = Отделы.id INNER JOIN Банки ON Сотрудники.Банк = Банки.id */ /* -- Запрос с условием, которое всегда будет True SELECT * FROM Сотрудники JOIN Отделы ON 1=1 */
  • Объединение таблиц – UNION
  • Соединение таблиц – операция JOIN и ее виды
  • Тест на знание основ SQL

Если материалы office-menu.ru Вам помогли, то поддержите, пожалуйста, проект, чтобы я мог развивать его дальше.

Как джойнить таблицу саму на себя

Есть Z-таблица c миллионами записей, мне нужно сделать (желательно. ) одну выборку.

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

ID DATE VOLUME
1 07.10.2019 123,78
2 08.10.2019 33,12
3 09.10.2019 13,54
4 10.10.2019 3,35

Мне нужно получить строку: МаксКол: 123,78, его дата: 07.10.2019, всего: 173,79.
select
id
max( VOLUM )
sum( VOLUME )
from ztab
group by id.

Код, приведенный выше, дает желаемый результат, но без даты, к которой относится максимальное количество. Вставка даты в select и в group by нарушает логику и не собирает общую сумму (данные в разрезе дней, а не айдишника).

Буду очень рад любым подсказкам!

_________________
Заранее благодарен за помощь. С уважением, Primat.

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Пн, окт 07 2019, 15:23

Добрый день.
Как вариант — заджойнить таблицу саму на себя, условие джойна volume = max( volume ). Только надо придумать что делать если будет несколько одинаковых максимальных значений..

PS. проверил , возникают проблемы с условием по максимальному значению в JOIN.
Тогда использовать промежуточный CDS view в котором считать сумму и максимум и затем этот view джойнить с исходной таблицей по volume = max_volume.

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Пн, окт 07 2019, 16:19

Старший специалист

Извиняюсь за древность, но у нас версия 702. У нас нет CDS view

_________________
Заранее благодарен за помощь. С уважением, Primat.

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Пн, окт 07 2019, 17:23

Старший специалист

А такое работает?

SELECT z~id z~date z~volume SUM( z2~volume ) AS sum
FROM ztab AS z INNER JOIN ztab AS z2
ON z2~id = z~id
INTO TABLE t
WHERE volume = ( SELECT MAX( volume ) FROM ztab AS z3
WHERE z3~id = z~id )
GROUP BY z~id z~date z~volume
ORDER BY z~volume.

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

Последний раз редактировалось LAT Ср, окт 09 2019, 17:59, всего редактировалось 1 раз.

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Вт, окт 08 2019, 07:18

Старший специалист

Цитата:
нужно сделать (желательно. ) одну выборку

А правильно ли идеологически так поступать вообще, на реальной, возможно высоконагруженной СУБД (а если ещё и блокировочник типа ДБ/2)?
М.б. однопроходный скан всей таблицы с подсуммированием средствами абапа будет менее безжалостный к другим толпящимся в системе пользователям?

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Вт, окт 08 2019, 17:10

Гуру-модератор

По поводу даты для максимального volum, как-то так (упрощая вариант LAT):

SELECT z~id z~date z~volume
FROM ztab
INTO TABLE t
WHERE volume = ( SELECT MAX( volume ) FROM ztab ).

Если сделать индекс по volum, работать будет моментально.
В Oracle можно без подзапроса написать с помощью keep dance rank, но это будет для SAP Native SQL, его использовать не рекомендуется

А вот общую сумму по volum придется отдельным селектом вытаскивать и в нем БД придется все строки таблицы на своей стороне перебрать.

select sum(volume) into l_volum_sum
from ztab

_________________
Удача — результат нашего желания (© А. Нортон)

Заголовок сообщения: Re: Помогите сделать select из таблицы с миллионами строк
Добавлено: Вт, окт 08 2019, 17:14

Гуру-модератор

pberezin написал:
Цитата:
нужно сделать (желательно. ) одну выборку

А правильно ли идеологически так поступать вообще, на реальной, возможно высоконагруженной СУБД (а если ещё и блокировочник типа ДБ/2)?
М.б. однопроходный скан всей таблицы с подсуммированием средствами абапа будет менее безжалостный к другим толпящимся в системе пользователям?

Не скажу за DB/2, но с нормальной БД (Oracle) как раз-таки безжалостно таскать по сети с БД на сервер приложений миллионы строк ради того чтобы на выходе получить одно число.

_________________
Удача — результат нашего желания (© А. Нортон)

Страница 1 из 1 [ Сообщений: 7 ]

Часовой пояс: UTC + 3 часа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB

SAP форум.RU © 2000-. Михаил Вершков

Логотип © 2006 Андрей Горшков

Основан 27 ноября 2000 года

Объединение таблицы с самой собой

Author24 — интернет-сервис помощи студентам

Доброго времени суток. Такой вопрос имеется таблица с такой структуры
id, secret_key ,date, status
задача такая, найти все значения, где status = 2 и для каждого из этих значений найти предыдущее со status = 1 и таким же secret_key.
У меня запрос делает не совсем то, что требуется. Он ко всем найденным со status =2 подставляет предыдущие status = 1

1 2 3
SELECT * FROM TABLES AS ones LEFT JOIN TABLES AS two ON ones.secret_key = two.secret_key AND ones.date > two.date AND two.`status` = 1 WHERE ones.`status`= 2
Здесь вы можете заказать любую студенческую или школьную работу.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *