За последние 24 часа нас посетили 17468 программистов и 1715 роботов. Сейчас ищут 1697 программистов ...

[вынесено из] Запрос с объединением трёх таблиц

Тема в разделе "PHP и базы данных", создана пользователем miketomlin, 10 апр 2023.

  1. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    Просто JOIN – это та же хрень (CROSS). Здесь нужен именно LEFT JOIN – расширить записи одной таблицы полями из др. Он круто оптимизируется, когда присоединяются данные из «словарей». Нет даже попытки изменить кол-во записей из осн. таблицы, дублируя их.
     
    #1 miketomlin, 10 апр 2023
    Последнее редактирование: 10 апр 2023
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    Миша, не могу согласиться. LEFT JOIN одна из хреней, которые надо использовать редко. Когда ты точно знаешь, что он необходим. Так же как null-able поля. Так же как DISTINCT. Всё это вещи хорошие, для своего правильного места. Но когда их лепят просто ВЕЗДЕ, это признак что код говнякают, а не пишут.
    Ибо отсутствующая запись в "словаре" это, блин, АХТУНГ! Неконсистентные данные. Ошибочная ситуация должна приводить к поведению, на которое обратишь внимание и исправишь. А не "авось и так будет работать".
    --- Добавлено ---
    @Булат Азат улы сейчас совсем запутается. Приношу свои извинения ))
    --- Добавлено ---
    Вот почитай чтобы понимать больше про соединения (join): нагуглил по быстрому - https://learndb.ru/articles/article/30
    ( Update: ^^^ это был совет ТСу, а не miketomlin )
     
    Булат Азат улы нравится это.
  3. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    Это понятно. Но еще больший АХТУНГ – потеря в выборке требуемых записей из-за «проблемы» (это не всегда проблема) с каким-то словарем! Ты наверняка знаешь о возможностях СУБД по жесткому контролю полноты словарей. Неполнота тоже может быть допустима: вывод пустых ячеек или черточек в них вместо NULL – вполне вменяемая практика.

    LEFT JOIN предназначен для раскрытия внешних ключей (задача ТС'а). Когда ты говоришь, что это редкая задача, я даже не знаю, что ответить.

    P.S. В мускуле INNER и CROSS (и просто JOIN) – полные эквиваленты, так что для меня это одна хрень. Т.е. (INNER) JOIN – в данном случае тоже хрень, если кого-то напрягло слово CROSS.
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    Давай по порядку. Во имя истины, а не сратча для )))

    Утверждение:
    Всё смешалось здесь. Нет такого термина "расширение" в РСУБД. Все join-ы, предназначены для, внезапно™, соединения данных из разных множеств по какому-то условию (не обязательно равенству) в общие строки.
    Для простоты ограничимся равенством значений. И будем говорить только о таблицах, хотя объединять можно целые выражения или "подзапросы".

    Внешнее (LEFT или RIGHT) соединение отличается тем, что при невыполнении условия объединения, одна из половинок всё равно будет присутствовать в результате. А на месте отсутствующих данных другой половины будут NULL. Оптимизация здесь вообще не при чем — непонятно с чего здесь этот термин. Это математические отношения, а не способ что-то ускорить.
    Про "дубли" тоже невпопад. Повторяющиеся данные могут появиться когда объединяемые таблицы связаны один-ко-многим. Такое отношение даст повторы для данных из таблицы со стороны где "один-" ))) И здесь нет разницы INNER или LEFT, всё равно будут дубли.
     
    #4 artoodetoo, 11 апр 2023
    Последнее редактирование: 11 апр 2023
    Булат Азат улы нравится это.
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    Утверждение:
    Откуда такое вообще? Внешнее соединение предназначено для нахождения всех записей, для которых есть данные хотябы в одной (здесь в левой - LEFT) из таблиц. И допускает отсутствие связанных данных в другой таблице. Внешние ключи (foreign keys) это отдельная тема. Не к месту употребил.

    Утверждение:
    Для тебя возможно, а вообще — нет. INNER JOIN можно записать как просто JOIN.
    Но CROSS JOIN это особый вид соединения - перекрестное.

    Как это принято в интернетах, покажем в картинках для простоты:
    img_innerjoin.gif vs. img_leftjoin.gif vs. img_crossjoin.png
    --- Добавлено ---
    Для CROSS JOIN не надо писать условие ON. Какие-то диалекты, например Postgress, это прямо запрещает, выдаёт ошибку «syntax error at or near "ON"»
    Что касается "В мускуле полные эквиваленты", то MySQL не выдаст ошибку синтаксиса, а проглотит. Исторически так сложилось, что он многие ошибки игнорит. Но вообще по стандартам "ON" там лишний и соединение это имеет отдельный смысл. CROSS JOIN скорее аналог перечисления таблиц через запятую во FROM, а никак не INNER JOIN !!!

    Короче, призываю правильно пользоваться терминологией и не косячить, даже если синтаксическая ошибка не возникает. Логические ошибки куда хуже!
    --- Добавлено ---
    В исходной теме ТС никак не намекал что ему надо чтобы слева было, а справа могло быть пусто. ))) Но ты стал "оптимизировать" и проталкивать внешнее соединение. П о ч е м у ?

    Утверждение:
    надо внимательно читать прежде чем не знать что ответить:
    Я говорю: НАДО использовать редко, а не редкая задача. И аргументирую почему.
    Надо стараться писать правильно, надо знать матчасть, надо делать так, чтобы ошибочные данные себя обнаруживали, а не маскировать проблемы. Хорошо бы использовать внешние ключи чтобы исключить саму возможность неправильных данных для многих кейсов. Нет смысла в LEFT JOIN просто сцк везде. :)

    Peace!
     
    Булат Азат улы нравится это.
  6. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.839
    Симпатии:
    651
    @artoodetoo, ну, раз пошла такая пьянка, тоже попробую объяснить на пальцах...

    device-record-1 model-name marka-name
    device-record-2 model-name marka-name
    (имена моделей/марок могут быть разные).

    Не может быть такого (когда присоединяются данные из «словарей»):
    device-record-1 model-name marka-name
    device-record-1 model-name marka-name
    device-record-2 model-name marka-name
    device-record-2 model-name marka-name
    (сокращения кол-ва записей тоже быть не может без доп. фильтрации, независимо от полноты словарей, – это и отличает LEFT JOIN от JOIN).

    Да, СУБД умеет оптимизировать выполнение запросов, когда обрабатываемые данные имеют определенные ограничения. Не нужно стрелять из пушки по воробьям.

    ТС как раз-таки «раскрывает внешние ключи» – по id-шкам «добирает» данные из соответствующих словарей. Так что все очень даже к месту! Странно, что кто-то «понимающий» этого не видит.

    Здесь написано, что (INNER) JOIN и CROSS (с WHERE) – одна хрень. Не решает задачу ТС'а.

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