MySQL — разница между двумя операторами

#mysql #sql #join #left-join

#mysql #sql #Присоединиться #левое соединение

Вопрос:

Я заметил этот SQL-запрос в документации:

 UPDATE pages page
LEFT JOIN pages parentpage ON page.pid = parentpage.uid
LEFT JOIN pages grandparentpage ON parentpage.pid = grandparentpage.uid
LEFT JOIN pages grandgrandparentpage ON grandparentpage.pid = grandgrandparentpage.uid
SET page.is_hidden = 0
WHERE page.uid = 5
OR page.pid = 5
OR parentpage.pid = 5
OR grandparentpage.pid = 5
OR grandgrandparentpage.pid = 5;
  

Разве это не то же самое, что:

 UPDATE pages page
SET page.is_hidden = 0
WHERE page.uid = 5
OR page.pid = 5;
  

PID и UID фильтруются предложением where равным 5 . Поэтому я не понимаю, почему это объединение было бы важно.

Но, может быть, я упускаю суть?

Любая помощь приветствуется.

Заранее спасибо.

Комментарии:

1. ЛЕВОЕ СОЕДИНЕНИЕ при ОБНОВЛЕНИИ — это странная вещь

2. Разве это не то же самое, что и No. Создайте 4 цепочки строк, где только grandgrandparentpage.pid = 5 и сравните результаты для этих запросов. 1-й запрос обновит все строки, тогда как 2-й — только 2 строки.

3. @Strawberry Почему бы и нет? Представьте, что есть только одна строка с uid = 5 , и она должна быть (не) помечена как скрытая. Обновляется только таблица mostleft…

4. Похоже, вы имеете дело с данными, которые являются иерархическими по своей природе. Я бы проявил особую осторожность при изменении любой существующей документации. 2 оператора обновления не совпадают. Первый использует левые соединения, чтобы имитировать дочернее родительское отношение для обновления

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

Ответ №1:

Вы что-то упускаете. См. db-fiddle . Первый SQL обновит не только строку с uid 5, но и ее дочерний элемент, внук и правнук, если они существуют.

Комментарии:

1. Но здесь таблица соединяется сама с собой. Они называют это parent, grandparent и т. Д., Но они всегда используют таблицу pages. Разве не все, что содержится в таблице pages, уже охвачено первым выбором (страница pages)? страница страниц => Таблица страниц с именем заполнителя страница страниц родительская => Таблица страниц с именем заполнителя родительская Или я ошибаюсь?

2. Представьте, что у вас было 4 идентичных таблицы (клоны друг друга с дублированными строками) с именем page , parentpage , grandparentpage и grandgrandparentpage на которых выполнялись соединения. Каковы будут результаты? Фактический SQL эквивалентен этому сценарию.

Ответ №2:

Они разные, потому что первый запрос обновляет все дочерние, внучатые и внучатые дочерние строки строки pid=5 или uid=5 . Второй обновит только сами строки.

Вот пример того, как запросы отличаются:

 |uid|pid| first query                 | second query     |
| 1 | 5 | Yes, page.pid=5             | Yes. page.pid=5  |
| 5 | 6 | Yes, page.uid=5             | Yes. page.uid=5  |
| 6 | 7 | Yes, parentpage.pid=5       | No               |
| 7 | 8 | Yes, grapdppage.pid=5       | No               |
| 8 | 9 | Yes, grandgrandppage.pid=5  | No               |
| 9 | 10| No                          | No               |
  

Комментарии:

1. Но parentpage, grandparentpage и т. Д. Берутся из одной и той же таблицы (страниц). Разве они уже не охвачены страницей pages (поскольку родительская страница pages по-прежнему является таблицей pages)? Я должен уточнить, что это реальный пример, который я получил. Это не заполнитель, который я включил. На мой взгляд, если parentpage grandparentpage и т. Д. Являются просто псевдонимами (не так ли?), Все уже охвачено вторым оператором (или, как я спрашивал, я (все еще) пропускаю его)…

2. Нет. Эта структура называется иерархией. Одно условие охватывает только один уровень, поэтому первый запрос возвращает 5 уровней, в то время как второй возвращает только 2. Ни один из них не возвращает бесконечную глубину. Попробуйте!