我正在编写一些带有多个子查询和大量连接的 SQL 查询,包括子查询内部和子查询的结果表。
我们没有使用视图,所以这是不可能的。
写完之后,我看着它,挠头想知道它在做什么,因为我无法理解它。
你用什么样的格式来尝试清理这样的混乱?可能是缩进?
我正在编写一些带有多个子查询和大量连接的 SQL 查询,包括子查询内部和子查询的结果表。
我们没有使用视图,所以这是不可能的。
写完之后,我看着它,挠头想知道它在做什么,因为我无法理解它。
你用什么样的格式来尝试清理这样的混乱?可能是缩进?
对于大型查询,我倾向于非常依赖使用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 tablename
WHERE value in
(SELECT *
FROM tablename2
WHERE condition)
ORDER BY column
表别名和简单的一致性将使您走得更远
看起来不错的是主要关键字 SELECT、FROM、WHERE(等等)的断行。
连接可能更棘手,缩进连接的 ON 部分会将其重要部分带到前面。
在同一级别上打破复杂的逻辑表达式(连接和 where 条件)也有帮助。
逻辑上相同级别的语句缩进(子查询、左括号等)
将所有关键字和标准函数大写。
真正复杂的 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'
所以,最后总结一下——一致性最重要。
格式化 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 查询。
一般来说,我遵循一组简单的分层格式规则。基本上,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
哇,这里有很多回复,但我在很多人中没有看到的一件事是评论!我倾向于在整个过程中添加很多注释,尤其是对于大型 SQL 语句。格式很重要,但放置得当且有意义的注释非常重要,不仅对您,对需要维护代码的可怜人来说;)
一个古老的问题,有一千种意见,没有一个正确的答案,也是我的最爱之一。这是我的两分钱。
关于子查询,最近我发现使用“极端”缩进和添加评论更容易理解:
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
至于其他分,我只在第一个单词上使用大写。通过连续查询页面,可以更轻松地确定新查询何时开始。
当然,您的里程会有所不同。
将其放在视图中以便更容易可视化,也许将屏幕截图作为文档的一部分。您不必保存视图或将其用于任何其他目的。
当然可以缩进,但您也可以将子查询与注释分开,使您的别名真正有意义并指定它们引用的子查询,例如innerCustomer、outerCustomer。
在某些情况下,公用表表达式确实可以帮助将查询分解为有意义的部分。