Форматирование понятных и читаемых SQL-запросов
Я пишу некоторые SQL-запросы с несколькими подзапросами и множеством соединений повсюду, как внутри подзапроса, так и в результирующей таблице из подзапроса.
мы не используем, так что это исключено.
после написания я смотрю на него и чешу голову, задаваясь вопросом, что он вообще делает, потому что я не могу следовать за ним.
какое форматирование вы используете, чтобы попытаться разгрести такой бардак? Возможно, отступы?
11 ответов
С большими запросами я склонен полагаться на именованные результирующие наборы, используя 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
мальчик, это загруженный вопрос. :) Есть так много способов сделать это правильно, как есть умные люди на этом сайте. Тем не менее, вот как я держу себя в здравом уме при создании сложных операторов 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
Если вам интересно, я могу публиковать / отправлять макеты для вставок, обновлений и удалений, а также коррелированных подзапросов и сложных предикатов соединения.
это ответ на твой вопрос?
псевдонимы таблиц и простая согласованность помогут вам пройти долгий, долгий путь
то, что выглядит прилично, - это разрыв строк на основных ключевых словах SELECT, FROM, WHERE (etc..).
соединения могут быть сложнее, отступ на части соединений выводит важную часть его на передний план.
разбиение сложных логических выражений (соединений и условий) на одном уровне также помогает.
отступ логически тот же уровень оператора (подзапросы, открытие скобок и т. д.)
использовать все ключевые слова и стандартные функции.
действительно сложный SQL не будет уклоняться от комментариев - хотя обычно вы найдете их в SQL-скриптах, а не в динамическом SQL.
изменить пример:
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'
Итак, в конце подведем итог-согласованность имеет наибольшее значение.
Как правило, люди разбивают строки на зарезервированные слова и отступают от любых подзапросов:
SELECT *
FROM tablename
WHERE value in
(SELECT *
FROM tablename2
WHERE condition)
ORDER BY column
В общем, я следую простому иерархическому набору правил форматирования. В принципе, ключевые слова, такие как SELECT, FROM, ORDER by all, идут по собственной линии. Каждое поле идет по своей линии (рекурсивно)
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
)
Мне нравится использовать что-то вроде:
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
на только true и right способ форматирования 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
;
;)
серьезно, мне нравится использовать с предложениями (как уже предлагалось), чтобы приручить очень сложные SQL-запросы.
поместите его в представление, чтобы его было легче визуализировать, возможно, сохраните скриншот как часть документации. Вам не нужно сохранять представление или использовать его для каких-либо других целей.
отступ, конечно, но вы также можете разделить подзапросы с комментариями, сделать ваши псевдонимы действительно значимыми и указать, к какому подзапросу они относятся, например, innerCustomer, outerCustomer.
общие табличные выражения могут действительно помочь в некоторых случаях разбить запрос на значимые разделы.
вековой вопрос с тысячью мнений и ни один правильный ответ, и один из моих любимых. Вот мои два цента.
что касается подзапросов, в последнее время мне стало легче следить за тем, что происходит с "экстремальным" отступом и добавлением комментариев:
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
что касается другого цента, я использую только верхний регистр на первом слове. Со страницами запросов запуска, это делает его немного легче выбрать, когда начинается новый.
ваш пробег будет конечно, разные.
Вау, много ответов здесь, но одна вещь, которую я не видел во многих комментариях! Я, как правило, добавляю много комментариев, особенно с большими инструкциями SQL. Форматирование важно, но хорошо размещено и имеет смысл комментарии чрезвычайно важны не только для вас, но и для бедной души, которой нужно поддерживать код;)