Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
格式化清晰可读的SQL查询_Sql_Plsql_Code Cleanup - Fatal编程技术网

格式化清晰可读的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 表别

我正在编写一些SQL查询,其中包含多个子查询和大量的连接,都在子查询和子查询生成的表中

我们没有使用视图,所以这是不可能的

写完之后,我看着它,挠头想知道它到底在做什么,因为我无法理解它


你用什么样的格式来试图清理这样的混乱?缩进?

通常,人们在保留字上断行,并缩进任何子查询:

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
;