格式化清晰可读的SQL查询
我正在编写一些SQL查询,其中包含多个子查询和大量的连接,都在子查询和子查询生成的表中 我们没有使用视图,所以这是不可能的 写完之后,我看着它,挠头想知道它到底在做什么,因为我无法理解它格式化清晰可读的SQL查询,sql,plsql,code-cleanup,Sql,Plsql,Code Cleanup,我正在编写一些SQL查询,其中包含多个子查询和大量的连接,都在子查询和子查询生成的表中 我们没有使用视图,所以这是不可能的 写完之后,我看着它,挠头想知道它到底在做什么,因为我无法理解它 你用什么样的格式来试图清理这样的混乱?缩进?通常,人们在保留字上断行,并缩进任何子查询: SELECT * FROM tablename WHERE value in (SELECT * FROM tablename2 WHERE condition) ORDER BY column 表别
你用什么样的格式来试图清理这样的混乱?缩进?通常,人们在保留字上断行,并缩进任何子查询:
SELECT *
FROM tablename
WHERE value in
(SELECT *
FROM tablename2
WHERE condition)
ORDER BY column
表别名和简单的一致性将为您带来漫长的道路 看起来像样的是,在主关键字SELECT、FROM、WHERE等上断线 连接可能更复杂,缩进连接的一部分将其重要部分带到前面 打破复杂的逻辑表达式连接,在同一级别上的where条件也会有所帮助 逻辑上缩进同一级别的语句子查询、左括号等 将所有关键字和标准函数大写 真正复杂的SQL不会回避注释——尽管您通常会在SQL脚本中发现这些注释,而不是动态SQL 编辑示例:
总之,一致性是最重要的。把它放在一个视图中,这样更容易可视化,也许在文档中保留一个屏幕截图。您不必保存视图或将其用于任何其他目的。通常,我遵循一组简单的分层格式规则。基本上,诸如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
)
我喜欢使用类似于:
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
当然可以缩进,但您也可以使用注释将子查询拆分,使别名具有真正意义,并指定它们引用的子查询,例如innerCustomer、outerCustomer
在某些情况下,公共表表达式确实有助于将查询分解为有意义的部分。对于大型查询,我倾向于在很大程度上依赖使用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上运行这是一个由来已久的问题,有上千种观点,但没有一个正确答案,也是我最喜欢的问题之一。这是我的两分钱 关于子查询,最近我发现通过极端缩进和添加注释更容易了解发生了什么,如下所示:
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
至于另一分,我只在第一个字上用大写字母。有了run-on查询页面,当新的查询启动时,可以更容易地进行选择
当然,您的里程数会有所不同。男孩,这是一个很难回答的问题在这个网站上有很多聪明的人,也有很多方法可以做到这一点。也就是说,在构建复杂的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
如果您感兴趣,我可以发布/发送用于插入、更新和删除以及相关子查询和复杂连接谓词的布局
这是否回答了您的问题?格式化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查询。哇,这里有很多响应,但有一点我在很多地方都没有看到,那就是注释!我倾向于在整个过程中添加大量注释,尤其是对于大型SQL语句。格式很重要,但位置恰当且有意义的注释非常重要,不仅对你来说如此,对需要维护代码的可怜人来说也是如此 什么站台?SSMS和MySQL Workbench的插件可以为您美化SQL代码。好问题。我自己还没有找到令人信服的SQL格式规则。@Brian Driscoll,你知道MySQL Workbench的哪些插件?@Brian,我正在使用PL/SQL。是否有任何独立的脚本或工具可以美化代码?在那里我可以粘贴代码,它会给我一个美化的版本。WITH关键字很有趣。由于我可以在后面的几行中按名称引用结果集,因此肯定会使代码更清晰。CTE对于提高查询可读性非常有用,但不幸的是,它们有时会掩盖错误,使错误更难调试。如果CTE中发生错误,您将得到一个错误,它通常指向您的查询,而不是显示它发生的位置。如果CTE是嵌套的,那么调试就更加困难。似乎大多数人都同意white
空间我喜欢关注每一行的原子性。使用此模式,我可以快速扫描层次结构以查找节点,然后进行钻取。以我的经验来看,这种方法的主要缺点是打印输出会吃掉纸张。从积极的一面看,它们很少会对页面进行换行或换行。我喜欢这种布局的地方在于,当您试图找出为什么查询无法返回预期结果时,可以很容易地注释掉部分查询。在编写复杂查询时始终很重要。
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
;