2009-05-15 2 views
2

Я не думаю, что это делает никакой разницы в базу данных, но при объединении таблиц, которые заказывают вы предпочитаете записать условие:Условие соединения SQL A = B или обратное к B = A?

SELECT 
    ... 
    FROM AAA 
     INNER JOIN BBB ON AAA.ID=BBB.ID 
    WHERE ... 

ИЛИ

SELECT 
    ... 
    FROM AAA 
     INNER JOIN BBB ON BBB.ID=AAA.ID 
    WHERE ... 
+1

А также просто бросить это здесь ... как насчет SELECT * FROM AAA, BBB WHERE AAA.ID = BBB.ID – Travis

+3

T Pops Я не рекомендую никому использовать этот синтаксис. Он устарел в течение 17 лет и гораздо более подвержен ошибкам (случайные кросс-соединения), и их сложнее понять и поддерживать. – HLGEM

+0

Также невозможно выполнить определенные виды сложных объединений, не используя фактические статьи присоединения –

ответ

2

Я предпочитаю первый вариант , Вы переходите от A к B, поэтому порядок полей кажется более подходящим.

5

Я предпочитаю второй вариант, когда наступает первая написанная таблица.

Я думаю, что Linq требует, чтобы это было наоборот, хотя (вариант 1).

+0

Видимо, я единственный ... –

+0

@ Майкл Харен, я предпочитаю A = B, но вы не единственный. Я задал этот вопрос, чтобы убедиться, что я сумасшедший или нет, многие люди, с которыми я работаю, используют B = A! –

+0

Я тоже предпочитаю это. – CoverosGene

1

Нет разницы, но я бы на "AAA INNER JOIN ГЭБ ON AAA.ID = BBB.ID" для ясности (но с псевдонимами)

1

Я использую первый синтаксис AAA.ID = BBB.ID. Это делает код более легким для чтения, на мой взгляд, поскольку участники соединения следуют порядку таблицы.

2

Я не думаю, что это действительно имеет значение, но я предпочитаю

INNER JOIN BBB ON AAA.ID=BBB.ID 

, потому что это согласуется с LINQ.

2

Другой мягкий голос для AAA.ID = BBB.ID. Мне кажется, это имеет больше смысла, но это не имеет большого значения.

В касательно связанной заметке, однако, я недавно начал спрашивать, как я пишу тесты равенства. Я всегда предпочитал:

If ValueInQuestion = TestValue Then 
... 

То есть,

If fullMoonsThisMonth = 2 Then 
... 

В коде чужой я часто видел этот тест вспять, и он прослушивал меня на некоторое время. Я понял, что мое предпочтение основано на подошве, на котором формулировка звучит «лучше» на английском языке, и что иногда есть веская причина для того, чтобы поставить инвариантную главу слева. На языках с одним оператором для тестирования и присвоения равенства (например, VB, если вы не узнали образцы ...), компилятор остановит вас от случайного выполнения задания, когда вы собираетесь выполнить тест.

1

Я обычно использую оба, поскольку это не имеет никакого значения.

+0

За исключением случаев использования LINQ –

8

Я предпочитаю второй пример (B = A), потому что в соединении я перечисляю критерии, которые определяют, какие строки B должны быть включены. Другими словами, мне нужны все строки из B, где «X» относится к B. Это также непротиворечиво, когда мне нужно проверить критерии, выходящие за рамки только FK.Например:

SELECT 
    some_columns 
FROM 
    Table_A A 
INNER JOIN Table_B B ON 
    B.a_id = A.a_id AND 
    B.active = 1 

На мой взгляд, это не будет иметь тот же читаемость, если у меня был:

1 = B.active 

Также рассмотрим случаи, в которых вы присоединиться к критериям включает более одной таблицы:

SELECT 
    some_columns 
FROM 
    Table_A A 
INNER JOIN Table_B B ON 
    B.a_id = A.a_id AND 
    B.active = 1 
INNER JOIN Table_C C ON 
    C.a_id = A.a_id AND 
    C.b_id = B.b_id AND 
    C.category = 'Widgets' 

Для меня это очень ясно указывает на критерии включения строк из С.

+2

Именно поэтому я предпочитаю формат B = A, я чувствую, что я «объясняю», как B включается. –

+0

Том утверждает обоснование предпочтения лучше, чем я сделал в своем ответе. В принципе, предпочтение для последнего шаблона возникает в более сложных объединениях при объединении нескольких таблиц, встроенных представлений, в несколько предикатов. Это привычка следовать той же схеме и для более простых случаев, как в примере в исходном вопросе, соединяющем две таблицы с одним предикатом. – spencer7593

+1

Я раньше не думал об этом, но теперь, когда это предлагается, я думаю, что я изменю свои пути. +1 для приятного объяснения и явно закодированного примера. – DaveM

3

Это не имеет большого значения, оба правильные. Мое предпочтение - второе.

Мои предпочтения основаны на идее, что таблица BBB - это таблица, которую я добавляю в набор результатов, а работа под рукой связывает столбцы (выражения) из новой таблицы BBB с другими столбцами уже в наборе результатов , Это может иметь больше смысла в другом примере:

SELECT ... 
    FROM AAA a 
    JOIN BBB b ON (b.AAA_ID = a.ID) 
    JOIN CC c ON (c.AAA_ID = b.AAA_ID AND UPPER(c.FEE) IN ('FI','FO')) 
    JOIN DDD d ON (d.CC_ID = c.ID AND LEFT(d.DAH,2) = c.FEE) 

Да, это arbitarily сложный пример, но иногда реальный код делает это получить сложнее. При ссылке на несколько предикатов в условии соединения я считаю полезным, когда каждый предикат ссылается сначала на (слева) выражения из недавно присоединившейся таблицы.

Существуют и другие шаблоны, которые также помогают, например, когда основным ключом каждой таблицы является один столбец с именем «ID», а столбцы внешнего ключа обычно называются PARENTTABLE_ID, так что когда я вижу конструкцию типа a. ID = b.ID, то, что я вижу, является шаблоном для первичного ключа, связанного с первичным ключом (отношение «один к одному», которое не является нормативным паттерном). И когда я вижу b.FOREIGN_ID = c.FOREIGN_ID, то, что я вижу, является внешним ключом, который соединяется с внешним ключом. Опять же, не обычный шаблон, указывающий на это, может быть соединение «многие-ко-многим», или, возможно, сочетание быстрого доступа для производительности. Обычный шаблон, который я ищу в соединении parent-child, похож на child.PARENT_ID = parent.ID

Эти шаблоны неправильные или неправильные, только предпочтение. Я нахожу, что эти шаблоны не делают код, который выглядит правильно, но делает код «странным».

+0

Том Х. сделал лучшую работу, объясняя это, чем я, я согласен с его ответом по причинам, которые он дает. Если бы это был простой случай, это не имело бы значения. Предпочтение основано на следующем шаблоне, который мы находим полезным в более сложных случаях. – spencer7593

+0

+1 Для того, чтобы сделать ссылку на ответ Тома Х, я, возможно, не прочитал его без вашей заметки. – DaveM

0

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

Я лично предпочитаю перечислить последнюю таблицу второго (вариант 1). Это соглашение помогает, потому что я решил всегда использовать LEFT OUTER JOIN, когда это необходимо (а не ПРАВИЛЬНЫЙ ВЗГЛЯД), и мне не нужно думать о том, какая таблица будет справа или слева.

+0

Я немного смущен вами. Порядок таблиц в предложении FROM (и нужный набор результатов) определяет, указано ли внешнее соединение как LEFT или RIGHT. Порядок выражений в предикате соединения не зависит от внешнего соединения. – spencer7593

0

Давайте вспомним, что LINQ не является SQL, так почему он даже упоминается здесь? На вопросы SQL не должны отвечать ответы LINQ. Это просто странно и совершенно нерелевантно, на мой взгляд!

Оба примера приемлемы. Я предпочитаю второй пример, как это было бы у большинства разработчиков SQL. Это также зависит от типа SQL JOIN, который вы хотите использовать. Заголовок вопроса просто для «JOIN», но ваш пример использует INNER JOIN.

В данном случае для INNER JOIN это не имеет значения. Но имейте в виду, что оба примера будут создавать HASH MATCHED JOIN, который не идеален при работе с индексами. Loop Join намного эффективнее. Просто убедитесь, что вы считаете свои индексы, поскольку Hash Joins являются индикатором неэффективной индексации.

0

Не может ли это сделать разницу в производительности в зависимости от того, как индексируются две таблицы и на каком поле они соединены?

Оптимизатор запросов в некоторых механизмах БД может делать правильные вещи независимо от того, какой заказ вы указали, но только некоторое время с планом запроса и тестированием ответит точно.

Смежные вопросы