2011-03-28 15 views
26

我正在編寫一些SQL查詢,其中包含子查詢和子查詢結果表中的幾個子查詢和大量連接。格式化清晰可讀的SQL查詢

我們沒有使用視圖,所以這是不可能的。

寫完後,我正在看它,抓着我的腦袋想知道它甚至在做什麼,因爲我無法遵循它。

你用什麼樣的格式來嘗試清理這樣的混亂?縮進也許?

+0

什麼平臺?有SSMS和MySQL Workbench的插件可以爲你「美化」你的SQL代碼。 – 2011-03-28 15:41:40

+0

好問題。我還沒有爲SQL自己找到一個令人信服的格式化規則。 – 2011-03-28 15:42:25

+0

@Brian Driscoll,你知道MySQL Workbench的插件嗎? – dcarneiro 2011-03-28 15:45:12

回答

17

對於大量查詢,我傾向於使用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

+0

WITH關鍵字很有趣。絕對可以讓代碼更加清潔,因爲我可以在隨後的行中引用名稱的結果集。 – MxyL 2011-03-28 16:33:52

3

一般來說,人們打破保留字線,並縮進任何子查詢:

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

表的別名和簡單的一致性,將讓你很長,很長的路要走

看起來體面的斷裂線在主要關鍵字SELECT,FROM,WHERE(等..)。

連接可能會更棘手,縮進連接的ON部分將其重要部分帶到前面。

在同一級別上打破複雜的邏輯表達式(連接和條件)都有幫助。

縮進邏輯語句的同一級別(子查詢,打開支架等)

大寫的所有關鍵字和標準功能。

真正複雜的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' 

所以,在最後總結一下 - 一致性纔是最重要的。

2

將它放在一個視圖中,這樣可以更容易直觀化,也可以將屏幕截圖保留爲文檔的一部分。您不必保存視圖或將其用於任何其他目的。

3

一般來說,我遵循一個簡單的分層格式設置規則。基本上,諸如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 
    ) 
3

我喜歡用這樣的:肯定

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 
2

縮進,但你也可以分割子查詢了評論,讓您的別名命名真正有意義的東西並指定它們引用的子查詢,例如innerCustomer,outerCustomer。

公用表表達式在某些情況下可以幫助將查詢分解爲有意義的部分。

2

一個古老的問題的當前版本有一千個判斷,沒有一個正確的答案,和我的最愛之一。這是我的兩分錢。

至於子查詢,最近我發現更容易按照發生了什麼事與「極端」縮進和添加像這樣的評論:

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 

至於其他的分,我只用大寫在第一個字上。通過運行查詢頁面,可以在新文件啓動時輕鬆選擇。

當然,您的里程會有所不同。

9

男孩是這是一個加載的問題。 :)有很多方法可以做到這一點,因爲這個網站上有聰明的人。這就是說,這裏是我如何使自己保持清醒構建複雜的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 

如果你有興趣,我可以張貼/發送的插入,更新佈局和刪除以及相關子查詢和複雜的連接謂詞。

這是回答您的問題嗎?

+0

似乎大多數人都認同空白! – MxyL 2011-03-28 17:09:03

+2

我喜歡關注每一行的原子性。使用這種模式,我可以快速掃描我正在查找的節點的層次結構,然後鑽取。根據我的經驗,這樣做的主要缺點是打印件吃紙。積極的一面,他們很少包裝或流失頁面。 – 2011-03-28 19:12:11

+1

我對這種佈局的喜歡是,當您試圖找出爲什麼它不會返回預期結果時,很容易將部分查詢註釋掉。編寫複雜查詢時總是非常重要。 – HLGEM 2011-03-28 20:55:01

3

只有真實和正確的格式化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查詢。

2

哇,在這裏有很多的迴應,但有一件事我沒有看到很多是評論!我傾向於在整個過程中添加很多評論,尤其是對於大型SQL語句。格式是重要的,但很好的地位和有意義的評論是非常重要的,不只是爲你,而是可憐的靈魂誰需要維護代碼;)