SQL - Различие между этими Соединениями?

Я добавляю свой личный опыт, поскольку он кажется немного безопаснее, чем то, что было предложено в 2012 году:

  1. Выполнить brew doctor.
  2. Если вы получите следующее предупреждение:

    Warning: The /usr/local directory is not writable.
    

    запустите:

    sudo chown -R `whoami` /usr/local
    

    , чтобы исправить проблемы с разрешениями (как предложено также Крисом Фрисиной). В конце концов, снова запустите brew doctor, чтобы убедиться, что предупреждение исчезло.

  3. Теперь у вас должен быть

    Warning: You have uncommitted modifications to Homebrew
    

    , который может быть решен с помощью

    cd /usr/local/Library && git stash && git clean -d -f
    

    , как это было предложено самим доктором Бру. Команда сохраняет незавершенные изменения, чтобы вы могли вернуться и восстановить их при необходимости. Это казалось мне безопаснее, чем git reset --hard origin/master.

  4. Если хотите, проверьте официальное руководство по устранению неполадок , если шаги, предложенные здесь и другими пользователями SO, не решают вашу проблему.

6
задан Mike Dinescu 6 August 2009 в 18:22
поделиться

4 ответа

Ну, это порядок операций ..

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2
        LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
    ON t2.table2_ID = t1.table1_ID

можно переписать как:

SELECT
    t1.*
FROM
       table1 t1                                                       -- inner join t1
    INNER JOIN 
       (table2 t2 LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID)  -- with this 
    ON t2.table2_ID = t1.table1_ID                                     -- on this condition

Итак, сначала вы НАЛЕВАЙТЕ СОЕДИНЯЙТЕСЬ t2 с t3, в зависимости от условия соединения: table3_ID = table2_ID , затем вы ВНУТРЕННЕЕ СОЕДИНЕНИЕ t1 с t2 на table2_ID = table1_ID.

В вашем втором примере вы сначала ВНУТРЕННЕЕ СОЕДИНЯЕТЕСЬ t1 с t2, а затем СОЕДИНЯЕТЕСЬ СЛЕВА с результирующим внутренним соединением с таблицей t3 при условии table2_ID = table1_ID.

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID        

может быть переписанным как:

SELECT
    t1.*
FROM
        (table1 t1 INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID) -- first inner join
    LEFT JOIN                                                           -- then left join
        table3 t3 ON t3.table3_ID = t2.table2_ID                        -- the result with this

РЕДАКТИРОВАТЬ

Прошу прощения. Мое первое замечание было неправильным. Два запроса дадут одинаковые результаты, но может быть разница в производительности, поскольку первый запрос может выполняться медленнее, чем второй запрос в некоторых случаях (когда таблица 1 содержит только подмножество элементов в таблице 2), поскольку LEFT JOIN будет сначала выполняться - и только потом пересекаться с table1.

5
ответ дан 9 December 2019 в 22:38
поделиться

Для вашего конкретного примера, я не думаю, что должна быть какая-либо разница в сгенерированных планах запросов, но определенно разница в удобочитаемости. Ваш второй пример НАМНОГО легче следовать.

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

SELECT    t1.*
FROM    table1 t1
    LEFT JOIN table2 t2 ON t2.table2_ID = t1.table1_ID
    INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID

-- may not produce the same results as...

SELECT    t1.*
FROM    table1 t1
    LEFT JOIN table2 t2
        INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
    ON t2.table2_ID = t1.table1_ID

Основываясь на том факте, что порядок объединений ДЕЙСТВИТЕЛЬНО имеет значение для многих case - следует тщательно продумать, как вы пишете синтаксис соединения. Если вы обнаружите, что второй пример - это то, что вы действительно пытаетесь выполнить, я бы подумал о переписывании запроса, чтобы вы могли больше внимания уделять порядку ваших объединений ...

SELECT    t1.*
FROM    table2 t2
        INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
        RIGHT JOIN table1 t1 ON t2.table2_ID = t1.table1_ID
4
ответ дан 9 December 2019 в 22:38
поделиться

Лучший способ увидеть, чем отличаются эти два запроса, - это сравнить план запроса для обоих этих запросов.

Нет никакой разницы в наборах результатов для этих IF в таблице 3 всегда есть строки для данной строки в таблице 2.

Я пробовал это в своей базе данных, и разница в планах запросов заключалась в том, что 1. Для первого запроса оптимизатор решил сначала выполнить объединение таблиц table2 и table 3. 2. Для второго запроса оптимизатор сначала решил объединить table1 и table2.

2
ответ дан 9 December 2019 в 22:38
поделиться

Вы не должны увидеть никакой разницы между двумя запросами, при условии, что ваш оптимизатор СУБД до нуля. Это, однако, даже для больших железных дорогостоящих платформ, не является предположением, в котором я был бы уверен, поэтому я не удивился бы, обнаружив, что планы запросов (и, следовательно, время выполнения) менялись.

0
ответ дан 9 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: