SQL (Structured Query Language) 是具備數據操縱和數據定義等多種功能的數據庫語言,這種語言具備交互性特色,能爲用戶提供極大的便利,數據庫管理系統應充分利用SQL語言提升計算機應用系統的工做質量與效率。git
身邊不少人工做中常常和SQL打交道, 但是每人的編寫SQL風格都獨樹一幟。github
恰好在githup上看到一個不錯的編碼風格, 在這裏給你們推薦一下。sql
小寫SQL比大寫SQL易讀,並且沒必要一直按住shift鍵。express
-- Good
select * from users
-- Bad
SELECT * FROM users
-- Bad
Select * From users
複製代碼
如下狀況最好將SQL寫在同一行中:dom
-- Good
select * from users
-- Good
select id from users
-- Good
select id, email from users
-- Good
select count(*) from users
複製代碼
這樣作的緣由很簡單,當全部內容都在一行時,仍然很容易閱讀。但一旦你開始添加更多的列或更復雜的代碼,若是是多行代碼就更容易閱讀:ide
-- Good
select
id,
email,
created_at
from users
-- Good
select *
from users
where email = 'example@domain.com 複製代碼
對於具備1或2列的查詢,能夠將這些列放在同一行上。對於3+列,將每一個列名放在它本身的行上,包括第一項:函數
-- Good
select id, email
from users
where email like '%@gmail.com'
-- Good
select user_id, count(*) as total_charges
from charges
group by user_id
-- Good
select
id,
email,
created_at
from users
-- Bad
select id, email, created_at
from users
-- Bad
select id,
email
from users
複製代碼
-- Good
select id, email
from users
where email like '%@gmail.com'
-- Bad
select id, email
from users
where email like '%@gmail.com'
複製代碼
一些SQL方言,如BigQuery支持使用雙引號,可是對於大多數方言,雙引號最終將引用列名。所以,單引號更可取:post
-- Good
select *
from users
where email = 'example@domain.com'
-- Bad
select *
from users
where email = "example@domain.com"
複製代碼
!=
而不用 <>
由於!=讀起來像「不等於」,更接近咱們大聲說出來的方式。ui
-- Good
select count(*) as paying_users_count
from users
where plan_name != 'free'
-- Bad
select count(*) as paying_users_count
from users
where plan_name <> 'free'
複製代碼
-- Good
select
id,
email
from users
-- Bad
select
id
, email
from users
複製代碼
當只有一個where條件時,將它保留在與where
相同的行上:
select email
from users
where id = 1234
複製代碼
當有多個縮進時,將每一個縮進比where更深一層。將邏輯運算符放在前一個條件的末尾:
select id, email
from users
where
created_at >= '2019-03-01' and
vertical = 'work'
複製代碼
-- Good
select *
from users
where id in (1, 2)
-- Bad
select *
from users
where id in ( 1, 2 )
複製代碼
in
值的長列表分紅多個縮進行-- Good
select *
from users
where email in (
'user-1@example.com',
'user-2@example.com',
'user-3@example.com',
'user-4@example.com'
)
複製代碼
-- Good
select * from users
select * from visit_logs
-- Bad
select * from user
select * from visitLog
複製代碼
-- Good select id, email, timestamp_trunc(created_at, month) as signup_month from users
-- Bad select id, email, timestamp_trunc(created_at, month) as SignupMonth from users
首先放置主鍵,而後是外鍵,而後是全部其餘列。若是表中有任何系統列(created_at、updated_at、is_deleted等),那麼將它們放在最後。
-- Good
select
id,
name,
created_at
from users
-- Bad
select
created_at,
name,
id,
from users
複製代碼
inner join
處理最好顯式,以便鏈接類型很是清楚:
-- Good
select
email,
sum(amount) as total_revenue
from users
inner join charges on users.id = charges.user_id
-- Bad
select
email,
sum(amount) as total_revenue
from users
join charges on users.id = charges.user_id
複製代碼
join
條件,將首先引用的表放在on
以後-- Good
select
...
from users
left join charges on users.id = charges.user_id
-- primary_key = foreign_key --> one-to-many --> fanout
select
...
from charges
left join users on charges.user_id = users.id
-- foreign_key = primary_key --> many-to-one --> no fanout
-- Bad
select
...
from users
left join charges on charges.user_id = users.id
複製代碼
-- Good
select
email,
sum(amount) as total_revenue
from users
inner join charges on users.id = charges.user_id
group by email
-- Bad
select
email,
sum(amount) as total_revenue
from users
inner join charges
on users.id = charges.user_id
group by email
複製代碼
當你有多個鏈接條件時,把它們放在各自的縮進行:
-- Good
select
email,
sum(amount) as total_revenue
from users
inner join charges on
users.id = charges.user_id and
refunded = false
group by email
複製代碼
-- Good
select
id,
name
from companies
-- Bad
select
companies.id,
companies.name
from companies
複製代碼
-- Good
select count(*) as total_users
from users
-- Bad
select count(*)
from users
-- Good
select timestamp_millis(property_beacon_interest) as expressed_interest_at
from hubspot.contact
where property_beacon_interest is not null
-- Bad
select timestamp_millis(property_beacon_interest)
from hubspot.contact
where property_beacon_interest is not null
複製代碼
-- Good
select * from customers where is_cancelled = true
select * from customers where is_cancelled = false
-- Bad
select * from customers where is_cancelled
select * from customers where not is_cancelled
複製代碼
as
重命名列名-- Good
select
id,
email,
timestamp_trunc(created_at, month) as signup_month
from users
-- Bad
select
id,
email,
timestamp_trunc(created_at, month) signup_month
from users
複製代碼
group by
時寫出列名而不要用序號-- Good
select user_id, count(*) as total_charges
from charges
group by user_id
-- Bad
select
user_id,
count(*) as total_charges
from charges
group by 1
複製代碼
-- Good
select
timestamp_trunc(com_created_at, year) as signup_year,
count(*) as total_companies
from companies
group by signup_year
-- Bad
select
count(*) as total_companies,
timestamp_trunc(com_created_at, year) as signup_year
from companies
group by signup_year
複製代碼
每一個when
應該在它本身的行上(case
行上沒有任何內容),而且應該比case
行縮進更深一層。then
能夠在同一條線上,也能夠在它下面的本身的線上。
-- Good
select
case
when event_name = 'viewed_homepage' then 'Homepage'
when event_name = 'viewed_editor' then 'Editor'
end as page_name
from events
-- Good too
select
case
when event_name = 'viewed_homepage'
then 'Homepage'
when event_name = 'viewed_editor'
then 'Editor'
end as page_name
from events
-- Bad
select
case when event_name = 'viewed_homepage' then 'Homepage'
when event_name = 'viewed_editor' then 'Editor'
end as page_name
from events
複製代碼
-- Good
with ordered_details as (
select
user_id,
name,
row_number() over (partition by user_id order by date_updated desc) as details_rank
from billingdaddy.billing_stored_details
),
final as (
select user_id, name
from ordered_details
where details_rank = 1
)
select * from final
-- Bad
select user_id, name
from (
select
user_id,
name,
row_number() over (partition by user_id order by date_updated desc) as details_rank
from billingdaddy.billing_stored_details
) ranked
where details_rank = 1
複製代碼
-- Good
with ordered_details as (
-- Bad
with d1 as (
複製代碼
你能夠把它放在同一行上,也能夠根據它的長度把它分紅多行:
-- Good
select
user_id,
name,
row_number() over (partition by user_id order by date_updated desc) as details_rank
from billingdaddy.billing_stored_details
-- Good
select
user_id,
name,
row_number() over (
partition by user_id
order by date_updated desc
) as details_rank
from billingdaddy.billing_stored_details
複製代碼
喜歡能夠關注公衆號: 終身幼稚園