Подтвердить что ты не робот

Форматирование Четкие и читаемые SQL-запросы

Я пишу некоторые SQL-запросы с несколькими подзапросами и множеством объединений везде, как внутри подзапроса, так и в результате таблицы из подзапроса.

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

После написания я смотрю на это и почесываю голову, думая, что это даже делает, потому что я не могу следовать за ней.

Какое форматирование вы используете, чтобы попытаться очистить такой беспорядок? Возможно, отступы?

4b9b3361

Ответ 1

С большими запросами я склонен много полагаться на именованные результирующие наборы, используя WITH. Это позволяет заранее определить набор результатов и упростить основной запрос. Именованные наборы результатов могут помочь сделать план запроса более эффективным, например, postgres сохраняет результирующий набор во временной таблице.

Пример:

WITH 
  cubed_data AS (
     SELECT 
        dimension1_id,
        dimension2_id,
        dimension3_id,
        measure_id,
        SUM(value) value
     FROM
        source_data
     GROUP BY
        CUBE(dimension1, dimension2, dimension3),
        measure
  ), 
  dimension1_label AS(
     SELECT 
        dimension1_id,
        dimension1_label
     FROM 
        labels 
     WHERE 
        object = 'dimension1'
  ), ...
SELECT 
  *
FROM  
  cubed_data
  JOIN dimension1_label USING (dimension1_id)
  JOIN dimension2_label USING (dimension2_id)
  JOIN dimension3_label USING (dimension3_id)
  JOIN measure_label USING (measure_id)

Пример немного ухищрен, но я надеюсь, что это показывает увеличение ясности по сравнению с встроенными подзапросами. Именованные результирующие наборы очень помогли мне, когда я готовил данные для использования OLAP. Именованные наборы результатов также необходимы, если у вас есть/хотите создавать рекурсивные запросы.

WITH работает по крайней мере в текущих версиях Postgres, Oracle и SQL Server

Ответ 2

Мальчик - это загруженный вопрос.:) Есть так много способов сделать это правильно, поскольку на этом сайте есть умные люди. Тем не менее, вот как я держу себя в здравом уме при построении сложных операторов sql:

select
    c.customer_id
   ,c.customer_name
   ,o.order_id
   ,o.order_date
   ,o.amount_taxable
   ,od.order_detail_id
   ,p.product_name
   ,pt.product_type_name
from
    customer c
inner join
    order o
    on c.customer_id = o.customer_id
inner join
    order_detail od
    on o.order_id = od.order_id
inner join
    product p
    on od.product_id = p.product_id
inner join
    product_type pt
    on p.product_type_id = pt.product_type_id
where
    o.order_date between '1/1/2011' and '1/5/2011'
and
    (
        pt.product_type_name = 'toys'
     or
        pt.product_type_name like '%kids%'
    )
order by
    o.order_date
   ,pt.product_type_name
   ,p.product_name

Если вам интересно, я могу отправлять/отправлять макеты для вставок, обновлений и удалений, а также коррелированные подзапросы и сложные предикаты соединения.

Отвечает ли это на ваш вопрос?

Ответ 3

Табличные псевдонимы и простая согласованность помогут вам долго и долго.

Что выглядит прилично - это разбить строки на ключевые слова SELECT, FROM, WHERE (и т.д.).

Совпадения могут быть более сложными, отступая от части ON, соединяющей основную часть ее с фронтом.

Также помогает помощь сложным логическим выражениям (объединениям и условиям условий) на одном уровне.

Отступы логически совпадают с уровнем оператора (подзапросы, открывающие скобки и т.д.)

Используйте все ключевые слова и стандартные функции.

Действительно сложный SQL не будет уклоняться от комментариев - хотя обычно вы находите их в сценариях SQL, а не динамическом SQL.

Пример EDIT:

SELECT a.name, SUM(b.tax)
FROM   db_prefix_registered_users a 
       INNER JOIN db_prefix_transactions b 
           ON a.id = b.user_id
       LEFT JOIN db_countries
           ON b.paid_from_country_id = c.id
WHERE  a.type IN (1, 2, 7) AND
       b.date < (SELECT MAX(date) 
                 FROM audit) AND
       c.country = 'CH'

Итак, в конце, чтобы подвести итог, наиболее важна последовательность.

Ответ 4

Как правило, люди разрывают строки на зарезервированных словах и отбрасывают любые подзапросы:

SELECT *
FROM tablename
WHERE value in
   (SELECT *
   FROM tablename2 
   WHERE condition)
ORDER BY column

Ответ 5

В общем, я следую простому иерархическому набору правил форматирования. В основном, ключевые слова, такие как SELECT, FROM, ORDER BY, все идут по своей линии. Каждое поле идет по собственной линии (рекурсивным образом)

SELECT 
    F.FIELD1,
    F.FIELD2,
    F.FIELD3
FROM
    FOO F 
WHERE 
    F.FIELD4 IN 
    (
        SELECT 
            B.BAR
        FROM 
            BAR B
        WHERE
            B.TYPE = 4
            AND B.OTHER = 7
    )

Ответ 6

Мне нравится использовать что-то вроде:

SELECT    col1,
          col2,
          ...
FROM
    MyTable as T1
INNER JOIN
    MyOtherTable as T2
        ON t1.col1 = t2.col1
        AND t1.col2 = t2.col2
LEFT JOIN
    (   
        SELECT 1,2,3
        FROM Someothertable
        WHERE somestuff = someotherstuff
    ) as T3
    ON t1.field = t3.field

Ответ 7

только правильный и правильный способ форматирования SQL:

SELECT t.mycolumn        AS column1
      ,t.othercolumn     AS column2
      ,SUM(t.tweedledum) AS column3
FROM   table1 t
      ,(SELECT u.anothercol
              ,u.memaw                  /*this is a comment*/
        FROM   table2       u
              ,anothertable x
        WHERE  u.bla       = :b1        /*the bla value*/
        AND    x.uniquecol = :b2        /*the widget id*/
       ) v
WHERE  t.tweedledee = v.anothercol
AND    t.hohum      = v.memaw
GROUP BY t.mycolumn
        ,t.othercolumn
HAVING COUNT(*) > 1
;

;)

Серьезно, хотя мне нравится использовать предложения WITH (как уже было предложено), чтобы приручить очень сложные SQL-запросы.

Ответ 8

Поместите его в представление, чтобы было легче визуализировать, возможно, сохранить снимок экрана как часть документации. Вам не нужно сохранять представление или использовать его для каких-либо других целей.

Ответ 9

Отступ, конечно, но вы также можете разбить подзапросы с комментариями, сделать имена псевдонимов действительно значимыми и указать, какой подзапрос они ссылаются, например. innerCustomer, внешнийклиент.

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

Ответ 10

Вековой вопрос с тысячей мнений и ни один правильный ответ, и один из моих фаворитов. Здесь мои два цента.

Что касается подзапросов, то в последнее время мне стало легче следить за тем, что происходит с "крайним" отступом и добавлением комментариев следующим образом:

SELECT mt.Col1, mt.Col2, subQ.Dollars
 from MyTable1 mt
  inner join (--  Get the dollar total for each SubCol
              select SubCol, sum(Dollars) Dollars
               from MyTable2
               group by SubCol) subQ
   on subQ.SubCol = mt.Col1
 order by mt.Col2

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

Ваш пробег, конечно, будет меняться.

Ответ 11

Ничего себе, много ответов здесь, но одна вещь, которую я не видел во многих, - это КОММЕНТАРИИ! Я обычно добавляю много комментариев, особенно с большими операторами SQL. Форматирование важно, но хорошо сделанные и содержательные комментарии чрезвычайно важны не только для вас, но и для бедной души, которым необходимо поддерживать код;)