Конференция "Базы" » "Непривязанный" join [MySQL]
 
  • Дмитрий С © (06.12.10 17:47) [0]
    К примеру надо найти автомобили с тем же брендом и двигателем, что и у автомобиля с id 33, как вам такой запрос:


    SELECT `a`.*
    FROM `auto` `a`
    LEFT JOIN `auto` `sub_a` ON `sub_a`.`id` = 33
    WHERE
    `a`.`brand` = `sub_a`.`brand`
    AND `a`.`engine` = `sub_a`.`engine`


    Спорная строчка выделена жирным.
    Или лучше все-таки выполнить запрос, а потом подставлять уже текст?
  • Дмитрий С © (06.12.10 17:52) [1]
    Хотя EXPLAIN, похоже говорит, что можно и так делать.

    1 SIMPLE sub_a const PRIMARY,IX_auto_brand,IX_auto_engine_model,IX_body_model,IX_model PRIMARY 4 const 1
    1 SIMPLE a ref IX_auto_brand,IX_auto_engine_model,IX_body_model,IX_model IX_auto_brand 767 const 7 Using where




    Похоже вопрос можно снять
  • Ega23 © (06.12.10 17:57) [2]
    По-идее это в where должно стоять. А оптимизатор - сам разобраться, что к чему.

    З.Ы. Интересная трактовка. Надо обдумать.
  • Кщд (06.12.10 18:51) [3]
    >Дмитрий С ©   (06.12.10 17:47)  
    чем не подходит in?
    зачем тут соединение, да ещё внешнее?
    чтобы случайно на индекс не встать?)
  • Дмитрий С © (06.12.10 18:58) [4]

    > Кщд   (06.12.10 18:51) [3]

    IN не подходит, т.к. сравнение идет по более, чем одному полю.
  • Дмитрий С © (06.12.10 19:01) [5]

    > З.Ы. Интересная трактовка. Надо обдумать.

    Надеюсь услышать результат :)
  • sniknik © (06.12.10 19:15) [6]
    я бы сделал так, если MySQL конечно позволил бы
    SELECT * FROM auto a
    INNER JOIN (SELECT brand, engine FROM auto WHERE id = 33) b
    ON a.brand = b.brand AND a.engine = b.engine

  • Кщд (06.12.10 19:39) [7]
    >Дмитрий С ©   (06.12.10 18:58) [4]
    row/table subqueries поддерживаются MySQL
  • Кщд (06.12.10 19:45) [8]
    >sniknik ©   (06.12.10 19:15) [6]
    согласно стандартной логике присоединяем к маленькой таблице большую:

    SELECT b.*
    FROM auto a
              INNER JOIN auto b
                ON a.brand = b.brand
                     AND a.engine = b.engine
    where a.id = 33


    оптимизатор должен преобразовать запрос именно в такой
    но у автора зачем-то внешнее соединение, что не отвечает его же поставленным условиям
    видимо, ему надо-таки выводить бренд и двигатель, а не просто находить совпадения
  • Дмитрий С © (07.12.10 06:04) [9]

    > sniknik ©   (06.12.10 19:15) [6]

    Поддерживает, конечно, хороший вариант, спасибо.
    PS. стыдно признаться, но я не знаю разницы между inner и left


    > оптимизатор должен преобразовать запрос именно в такой

    Какая же это оптимизация будет?
  • Кщд (07.12.10 07:18) [10]
    >Дмитрий С ©   (07.12.10 06:04) [9]
    запрос из (Кщд   (06.12.10 19:45) [8]) демонстрирует логику оптимизатора:
    1. выбрать одну запись из таблицы(желательно, если есть PK);
    2. затем присоединить к этой таблице другую.
    т.е. в общем случае к "меньшей" таблице присоединяется "бОльшая" - не наоборот

    разница между внешним и внутренним соединением критична - в случае с внешним объединением оптимизатор может не задействовать индекс(в Вашем случае по brand, engine), отдав предпочтение full table scan, что логично

    >Какая же это оптимизация будет?
    http://forge.mysql.com/wiki/How_does_the_MySQL_Optimizer_work

    лучше начать с основ - типы соединений таблиц, методы доступа, индексирование, селективность и пр.
  • Дмитрий С © (07.12.10 07:21) [11]

    > Кщд   (07.12.10 07:18) [10]

    Я понял логику, сразу не сообразил, спасибо.
  • Anatoly Podgoretsky © (07.12.10 08:57) [12]
    > Дмитрий С  (07.12.2010 06:04:09)  [9]

    Обычно это описано в документации, не говоря уже об Интернет.
  • Дмитрий С © (07.12.10 09:26) [13]

    > Anatoly Podgoretsky ©   (07.12.10 08:57) [12]

    Да это понятно. Читал и не раз, просто почти никогда кроме LEFT JOIN ничего не использовал, поэтому забываю.
 
Конференция "Базы" » "Непривязанный" join [MySQL]
Есть новые Нет новых   [134431   +15][b:0][p:0.001]