Вопрос в стиле SQL: INNER JOIN в предложении FROM или предложении WHERE? - PullRequest
3 голосов
/ 21 января 2011

Если вы собираетесь объединить несколько таблиц в запросе SQL, где, по вашему мнению, лучше разместить оператор соединения: в предложении FROM или в предложении WHERE?

Если вы собираетесьсделайте это в предложении FROM, как вы отформатируете его так, чтобы оно было четким и читаемым?(Я имею в виду отступы, переносы строк и пробелы в целом.)

Есть ли у каждого преимущества / недостатки?

Ответы [ 8 ]

8 голосов
/ 21 января 2011

Я склонен использовать предложение FROM или, вернее, само предложение JOIN, с отступом (например, с использованием псевдонимов):

SELECT t1.field1, t2.field2, t3.field3
FROM table1 t1
  INNER JOIN table2 t2
    ON t1.id1 = t2.id1
  INNER JOIN table3 t3
    ON t1.id1 = t3.id3

Это сохраняет условие соединения близко к тому месту, где оно сделано. Мне легче понять этот путь, чем пытаться просмотреть предложение WHERE, чтобы выяснить, что именно объединяется и как.

6 голосов
/ 21 января 2011

При создании ВНЕШНИХ СОЕДИНЕНИЙ (ANSI-89 или ANSI-92) местоположение фильтрации имеет значение, поскольку критерии, указанные в предложении ON, применяются до создания СОЕДИНЕНИЯ . Критерии для таблицы OUTER JOINed, представленные в предложении WHERE, применяются после создания JOIN . Это может привести к очень разным наборам результатов.

Для сравнения, ВНУТРЕННИЕ СОЕДИНЕНИЯ не имеют значения, если критерии указаны в предложениях ON или WHERE - результат будет таким же. Тем не менее, я стараюсь сохранить в чистоте предложение WHERE - все, что связано с таблицами JOINed, будет в соответствующем предложении ON. Сохраняет поиск с помощью предложения WHERE, поэтому синтаксис ANSI-92 более читабелен.

1 голос
/ 21 января 2011

Я предпочитаю предложение FROM, если ни по какой другой причине оно не различает результаты фильтрации (от декартового произведения) просто между отношениями внешнего ключа и между логическим ограничением.Например:

SELECT * FROM Products P JOIN ProductPricing PP ON P.Id = PP.ProductId
WHERE PP.Price > 10

В отличие от

SELECT * FROM Products P, ProductPricing PP 
WHERE P.Id = PP.ProductID AND Price > 10

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

1 голос
/ 21 января 2011

Я почти всегда использую соединения ANSI 92, потому что проясняю, что эти условия предназначены для СОЕДИНЕНИЯ.

Обычно я пишу это так

FROM
    foo f
    INNER JOIN bar b
    ON f.id = b.id

иногда я пишу таккогда это тривиально

FROM
    foo f
    INNER JOIN bar b  ON f.id = b.id
    INNER JOIN baz b2  ON b.id = b2.id

Когда это не тривиально, я делаю первый путь

например

FROM 
   foo f
   INNER JOIN bar b 
   ON f.id = b.id  
      and b.type = 1

или

FROM 
   foo f
   INNER JOIN (
          SELECT max(date) date, id
          FROM foo 
          GROUP BY
             id) lastF
  ON f.id = lastF.id
      and f.date = lastF.Date

Или действительностранно (не уверен, правильно ли я получил парены, но предполагается, что это ЛЕВОЕ соединение с панелью таблицы, но для бара требуется внутреннее соединение с базой)

FROM 
     foo f
     LEFT JOIN (bar b
          INNER JOIN baz b2 
           ON b.id = b2.id
      )ON f.id = b.id
0 голосов
/ 21 января 2011

ANSI присоединяется.Я опускаю любые дополнительные ключевые слова в SQL, поскольку они только добавляют шум в уравнение.Нет такого понятия, как левое внутреннее соединение, не так ли?И по умолчанию простое соединение - это внутреннее соединение, поэтому нет особого смысла говорить «внутреннее соединение».

Тогда я в столбце выровняю вещи настолько, насколько это возможно.

Дело в том, чтобольшой сложный SQL-запрос может быть очень трудным для понимания, поэтому, чем больше порядка, наложенного на него, чтобы сделать его более читабельным, тем лучше.Любое тело, рассматривающее запрос, чтобы исправить, изменить или настроить его, должно иметь возможность сразу ответить на несколько вопросов:

  • какие таблицы / представления участвуют в запросе?
  • каковы критерии для каждого объединения?Какова мощность каждого соединения?
  • что / сколько столбцов возвращается запросом

Мне нравится писать свои запросы, чтобы они выглядели примерно так:

select PatientID              = rpt.ipatientid ,
       EventDate              = d.dEvent       ,
       Side                   = d.cSide        ,
       OutsideHistoryDate     = convert(nchar, d.devent,112) ,
       Outcome                = p.cOvrClass    ,
       ProcedureType          = cat.ctype      ,
       ProcedureCategoryMajor = cat.cmajor     ,
       ProcedureCategoryMinor = cat.cminor
from      dbo.procrpt rpt
join      dbo.procd   d   on d.iprocrptid   = rpt.iprocrptid
join      dbo.proclu  lu  on lu.iprocluid   = d.iprocluid
join      dbo.pathlgy p   on p.iProcID      = d.iprocid
left join dbo.proccat cat on cat.iproccatid = lu.iproccatid
where procrpt.ipatientid = @iPatientID
0 голосов
/ 21 января 2011

Я определенно всегда делаю свои СОЕДИНЕНИЯ (любого типа) в моем предложении FROM.

То, как я их делаю, таково:

SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id

На самом деле, я вообще пойдуна шаг дальше и перенесите всю мою ограничивающую логику из предложения WHERE в предложение FROM, потому что это (по крайней мере, в MS SQL) загружает ограничение в начале, а это означает, что он уменьшает размер набора записей раньше в конструкции запроса (Я видел документацию, которая противоречит этому, но мои планы выполнения неизменно более эффективны, когда я делаю это таким образом).

Например, если я хотел выбрать только вещи в приведенном выше запросе, где t3.id =3, вы могли бы, но в предложении WHERE, или вы могли бы сделать это следующим образом:

SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id
    AND
    t3.id = 3

Лично я нахожу, что запросы, изложенные таким образом, очень удобочитаемы и удобны в обслуживании, но это, безусловно, вопросличных предпочтений, так что YMMV.

Несмотря на это, я надеюсь, что это помогает.

0 голосов
/ 21 января 2011

Используйте предложение FROM для соответствия стандартам ANSI-92.

Это:

select *
    from a
        inner join b
            on a.id = b.id
    where a.SomeColumn = 'x'

Не это:

select *
    from a, b
    where a.id = b.id
        and a.SomeColumn = 'x'
0 голосов
/ 21 января 2011

Вы должны помещать объединения в предложения Join, что означает предложение From. Может возникнуть другой вопрос о том, куда поместить фильтрующие операторы.

Относительно отступа, существует много стилей. Я предпочитаю делать отступы для связанных объединений и сохранять одинаковые основные положения, такие как «Выбрать», «Откуда», «Группировать по», «Имеет» и «По порядку» Кроме того, я поместил каждый из этих основных атрибутов и первую строку предложения On на отдельной строке.

Select ..
From Table1
    Join Table2
        On Table2.FK = Table1.PK
           And Table2.OtherCol = '12345'
           And Table2.OtherCol2 = 9876
    Left Join (Table3
        Join Table4
            On Table4.FK = Table3.PK)
        On Table3.FK = Table2.PK
Where ...
Group By ...
Having ...
Order By ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...