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
复制代码
喜欢能够关注公众号: 终身幼稚园