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

Я недавно задал вопрос о самосоединениях и получил отличный ответ.

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

Код работает нормально.Но я нене понимаю, КАК.

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

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

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

 anon16 авг. 2009 г., 16:50
Представьте, что event1 и event2 - это две совершенно не связанные таблицы, которые просто содержат одни и те же данные.

Ответы на вопрос(4)

Решение Вопроса

чтобы выписать два списка на первой части, помеченной как событие1 и одно событие2. Затем перечислите несколько записей в каждом списке (списки будут идентичны), теперь начинайте с ГДЕ в приведенном ниже описании.

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

FROM mm_eventlist_dates event1
JOIN mm_eventlist_dates event2 

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

  WHERE event1.id=$id

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

 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

О, только поля из того, чья дата начала мы выяснили.

 Nick Woodhams17 авг. 2009 г., 17:46
Спасибо за вашу помощь с этим.

ритерии - это то, что следует за предложением 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. Мы можем думать об этом как о наличии двух таблиц и выполнять соединение точно так же, как в сценарии реальных двух таблиц.

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

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

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

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)

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

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

WHERE event1.id=$id

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

SELECT event2.id, event2.startdate, event2.price
 Nick Woodhams17 авг. 2009 г., 17:47
Спасибо, ваш ответ был очень полезным.

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

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

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

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

    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
 Nick Woodhams17 авг. 2009 г., 17:47
Это самый простой пример, который я могу попросить. Большое спасибо.

Ваш ответ на вопрос