歡迎光臨
每天分享高質量文章

格式化 SQL 來提高效率

背景

已格式化的SQL並不比未格式化SQL執行地更快。資料庫可能真的不太在意你是否把逗號放在每個欄位名稱的前面或後面。為幫助你更理智和成為一名高效的SQL編寫者,我建議你遵循一些格式化的指導方針。在這篇文章裡,我將分享如何格式化SQL陳述句來提高工作效率。我對生產力這樣定義,能夠從SQL得到準確的結果,同時程式碼容易理解,修改和除錯。我只會專註於SELECT陳述句,它佔到我編寫SQL的99%。格式化SQL程式碼是非常個性的選擇,我很清楚,不同的人將鐘愛他們自己的格式化規則。

問題樣例

這是一個典型的SQL使用場景,業務上需要這樣的報表,它的資料在三個表中,分別是customer、sales 和 location。在2015年1月,報表需要顯示位於每一個郵政編碼區域的客戶數量和總銷售額。這應該是一個簡單的SQL陳述句,它連線三個表。

資料可能有問題

雖然SQL很容易,確保結果準確才是真正的挑戰,以下是許多可能的原因中的一個,包括:

  • 資料可能來自不同資料源。這意味著在不同的表中的無法保證取用完整性。簡單說,你不能假定 customer 表上的所有郵政編碼是有效的,同時在 location 表上也存在該問題。

  • 存取客戶資料的應用程式,可能沒有適當的資料驗證。可能已經存入不正確的郵政編碼。

  • postcode 表可能沒有所有郵政編碼。新的郵政編碼程式碼可能被引入,但自從上次更新還沒有新增到表中。



第一原則

對我來說,格式化SQL更多地是從SQL獲得正確的結果,因為它有明確的SQL,很容易跟蹤。我做的第一件事編寫獲取客戶總數的陳述句。這是個數字,我將在寫完整個陳述句後進行對比。

我寫的第一條陳述句是:

SELECT
COUNT(DISTINCT cust_id) AS count_customers
FROM
customers

Result:

count_customers
“10″

這個查詢很重要,因為它遵循了 第一原則(外部連結) 。因為沒有SQL連線,因此沒有依賴,我知道這是正確的客戶數量。我總是記下結果,因為我總是需要拿這個數字對比,在這篇文章是 10。

接下來我要做的就是新增必要的欄位和表到這個查詢。我強調新增這個詞,因為根據我遵循的格式化規則,我可以註釋掉查詢的元素來得到和我應用第一原則時相同的結果。下麵是我最終的格式化查詢,使用格式化查詢的方式。

格式化SQL

下麵是我推薦的格式化的SQL,緊接後面是我進行的格式化選擇的理由。

SELECT
0
,c.cust_post_code
,p.location
,COUNT(DISTINCT c.cust_id) number_customers
,SUM(s.total_amount) AS total_sales
FROM
customers c
JOIN post_codes p ON c.cust_post_code = p.post_code
JOIN sales s ON c.cust_id = s.cust_id
WHERE
1=1
AND s.sales_date BETWEEN '2015-01-01' AND '2015-01-31'
--AND s.order_id = 5
GROUP BY
c.cust_post_code
,p.location

總是使用表別名

這將會在你的SQL中得到證實。如果你不為參與查詢的每個欄位使用 別名(外部連結) ,有時候在後期,具有相同名稱的欄位新增到查詢中使用的某個表中。你的查詢和你的報表將出現一個錯誤(發現重覆的欄位名)。

逗號在欄位前

當除錯/測試我的查詢時,這讓我能輕易進行欄位註釋和取消註釋,不需要在查詢中修改任何其他行,以確保逗號在正確的地方。我看過一些文章,博主為了大事化小不得不改變另一個查詢的一部分,以確保逗號是正確的,但是你如果花大部分時間編寫和測試 SQL 陳述句,這是一個大問題。你按這種方式將會更有效率。這個在 SELECT 和 GROUP BY 查詢部分都工作地很好。

我在開發環境使用 SELECT 0,同時傾向於進入生產環境之前刪除它。它允許我把逗號放在所有欄位前。如果沒有 0,我想註釋掉c.cust_post_code,它是第一個欄位,我就必須註釋掉第二個欄位前面的逗號。我也會在 GROUP BY 子句做同樣的事情。0 可以消除這個額外的工作。

在新的一行JOIN

將JOIN陳述句放在一個新行的優勢包括:

  • 透過僅僅向下滾動JOIN陳述句串列就可以很容易地檢視查詢中所涉及到的所有表。

  • 使用 JOIN,相比將所有表和關係運算式都列在 WHERE 陳述句中,它可以將所有關係邏輯保持在一個地方。JOIN 陳述句也許不可能總是遵循在一行,但至少會在一個地方。

  • 註釋掉 JOIN 會相對比較容易。在除錯時,當你想知道哪個 JOIN 導致資料差異時,將很有用。


列樣式編輯

在處理大量的欄位時,列樣式編輯非常方便。下麵是我的第一次動畫GIF展示,顯示你如何註釋掉所有非聚合欄位。在實踐中我使用列樣式編輯(外部連結),不僅僅是註釋欄位還包括:

  • 大量建立索引

  • 在使用 UNION 陳述句時帶有長的欄位串列

  • 註 釋GROUP BY 子句長的欄位串列

測試查詢結果

我不得不使用外連線來列出所有客戶,因為並不是所有客戶的郵政編碼在 location 表中都能找到對應郵政編碼。我能夠做到這一點,透過在我的查詢中反覆包括和排除不同的欄位和表,確保我能夠與基於第一原則的最早查詢保持一致。

SELECT
0
,c.cust_post_code
--,p.location
,COUNT(DISTINCT c.cust_id) number_customers
,SUM(s.total_amount) AS total_sales
FROM
customers c
--LEFT OUTER JOIN post_codes p ON c.cust_post_code = p.post_code
JOIN sales s ON c.cust_id = s.cust_id
WHERE
1=1
AND s.sales_date BETWEEN '2015-01-01' AND '2015-01-31'
--AND c.cust_post_code = 2000
--AND p.post_code = 200
GROUP BY
c.cust_post_code
--,p.location

對我來說,像這樣格式化SQL,意味著我不必編寫為了檢查資料做單獨的測試。透過註釋掉一些行,我能使用第一原則來測試資料的準確性。這可以提高我的效率,以及報表的準確性。


英文出處:msiman.ga

譯文出處:伯樂線上-cucr
譯文連結:
http://blog.jobbole.com/85900/

贊(0)

分享創造快樂