Как работает Self-Join MYSQL?

Недавно я задал вопрос о Self-Joins, и я получил отличный ответ.

Запрос предназначен для поиска идентификатора, начальной даты и цены события2, следующего за событием1 на 1 день.

Код WORKS отлично. Но я не понимаю, КАК.

Может кто-нибудь объяснить так тщательно, как вы можете, какие разные части запроса и что они делают?

SELECT event2.id, event2.startdate, event2.price
FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
WHERE event1.id=$id

Я очень ценю вашу помощь, по какой-то причине мне очень тяжело обволакивает это.

Ответы

Ответ 1

То, как я попытаюсь понять это, состоит в том, чтобы выписать два списка на один фрагмент event1 и один event2. Затем перечислите несколько записей в каждом списке (списки будут идентичными) теперь начинаются с WHERE в описании ниже.

Мы берем данные из двух таблиц (одна и та же таблица используется дважды, но на данный момент пытаюсь игнорировать)

FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 

Это, вероятно, помогает читать остальное снизу вверх.

  WHERE event1.id=$id

Итак, мы хотим, чтобы запись из события1 имела указанный идентификатор записи. Предположительно, что ровно одна запись. Теперь мы выяснили, что после этого события закончилось.

 date_add(event1.enddate, INTERVAL 1 DAY)

Теперь, когда нам сообщаются записи из event2, они должны начинаться с этой даты,

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)

Теперь у нас есть две записи, какие поля мы хотим?

SELECT event2.id, event2.startdate, event2.price

О, просто поля из тех, чья дата начала мы выяснили.

Ответ 2

Когда вы создаете соединение в запросе, вы буквально делаете это - объединяя 2 таблицы вместе. Это может быть 2 разных или 2 одинаковых таблицы, это не имеет значения. При указании соединения создание псевдонима для таблицы (имя, которое относится к нему в остальной части запроса) полезно, если таблицы разные, и существенные, если они одинаковы. Ваш запрос принимает таблицу 1 (event1), которая имеет столбцы:

event1.id, event1.startdate, event1.price

и соединение таблицы 2 (событие2):

event2.id, event2.startdate, event2.price

который оставляет вас с результирующим набором:

event1.id, event1.startdate, event1.price, event2.id, event2.startdate, event2.price

Критерии для соединения указаны как:

ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)

который говорит: "Для каждой строки в событии1 присоедините строки (строки) в событии2, который имеет начальную дату в 1 день после начальной даты в событии1

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

WHERE event1.id=$id

Наконец, поскольку вам не нужна информация из события 1 об исходном событии, ваш оператор select просто выбирает столбцы event2 из набора результатов:

SELECT event2.id, event2.startdate, event2.price

Ответ 3

Самообслуживание работает, ссылаясь на одну и ту же таблицу дважды, используя разные критерии выбора. Подумайте о каждой ссылке на таблицу как на другую "Виртуальную таблицу", созданную путем фильтрации исходной таблицы. Как правило, одна из таблиц "фильтруется" с использованием предложения WHERE, а вторая "фильтруется" в предложении соединения. Это наиболее эффективный способ сделать это, также можно "фильтровать" оба в предложении join.

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

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

Рассмотрим таблицу людей, каждая из которых имеет уникальный идентификатор и столбец для отца

    id   name    fatherID
    1    Joseph  [null]
    2    Greg     1

    SELECT child.name as childName, father.name as fatherName
        FROM people as child
        INNER JOIN people as father on (child.fatherID = father.id)  

Уступит 1 строку

    childName   fatherName
    Greg       Joseph

Ответ 4

Соединение объединяет две таблицы, основанные на определенных критериях. Критерии - это то, что следует за предложением ON.

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

Например

Table foo         Table bar
+---+---+---+     +---+---+---+
| a | b | c |     | a | d | e |
+---+---+---+     +---+---+---+
| 1 | 2 | 3 |     | 1 | 0 | 0 |
+---+---+---+     +---+---+---+
| 1 | 3 | 4 |     | 2 | 9 | 3 |
+---+---+---+     +---+---+---+
| 1 | 3 | 5 |
+---+---+---+
| 2 | 4 | 6 |
+---+---+---+

Если мы делаем

select * from foo join bar on (foo.a = bar.a and foo.c > 4)

мы получим

foo join bar on (foo.a = bar.a and foo.c > 4)
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
| 1 | 3 | 5 | 0 | 0 |
+---+---+---+---+---+
| 2 | 4 | 6 | 9 | 3 |
+---+---+---+---+---+

Теперь,

SELECT event2.id, event2.startdate, event2.price 
FROM mm_eventlist_dates event1                     
JOIN mm_eventlist_dates event2 
ON event2.startdate = date_add(event1.enddate, INTERVAL 1 DAY)
WHERE event1.id=$id

этот запрос следует тому же принципу, но с двумя экземплярами таблицы mm_eventlist_dates, один с псевдонимом как event1, а другой как event2. Мы можем думать об этом как о двух таблицах и выполнить объединение так же, как в сценарии реальных двух таблиц.

Критерии присоединения в этом случае заключаются в том, что для table event2 стартовая комбинация соответствует enddate плюс один день таблицы event1.

Предложение where ограничивает то, что было выполнено в соединении, в этом случае он выполняет соединение только по строкам таблицы event1 с предоставленным идентификатором.