Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f02fe38

Browse files
committed
Day 43
1 parent 2efe249 commit f02fe38

File tree

1 file changed

+361
-0
lines changed

1 file changed

+361
-0
lines changed

‎0043_how_to_format_sql.md‎

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
Originally from: [tweet](https://twitter.com/samokhvalov/status/1722155043569496347), [LinkedIn post]().
2+
3+
---
4+
5+
# How to format SQL
6+
7+
> I post a new PostgreSQL "howto" article every day. Join me in this
8+
> journey – [subscribe](https://twitter.com/samokhvalov/), provide feedback, share!
9+
10+
There are various approaches to formatting SQL. There two major ones are:
11+
12+
1. **Traditional:** all keywords are uppercase, formatting is organized with a central whitespace pipe, advertised in Joe
13+
Celko’s "SQL Programming Style" book. One version is provided at [SQL Style Guide](https://www.sqlstyle.guide/).
14+
Example:
15+
16+
```sql
17+
SELECT a.title, a.release_date, a.recording_date
18+
FROM albums AS a
19+
WHERE a.title = 'Charcoal Lane'
20+
OR a.title = 'The New Danger';
21+
```
22+
23+
I personally find this style very old-fashioned, inconvenient, and cumbersome, and I prefer another one:
24+
25+
2. **Modern:** often (not always) lowercase keywords and left-align hierarchical indentation similar to what is used in
26+
regular programming languages. Example:
27+
28+
```sql
29+
select
30+
a.title,
31+
a.release_date,
32+
a.recording_date
33+
from albums as a
34+
where
35+
a.title = 'Charcoal Lane'
36+
or a.title = 'The New Danger';
37+
```
38+
39+
Here, we'll discuss a version of the latter ("modern") approach, derived from
40+
[Mozilla's SQL Style Guide](https://docs.telemetry.mozilla.org/concepts/sql_style.html).
41+
42+
The key difference from Mozilla's guide is that here we use lowercase SQL. The reason behind it is simple: an uppercase
43+
SQL makes more sense when it's embedded into a different language, to help distinguish it from the surrounding code.
44+
45+
But if you work with large query texts provided separately in various SQL editors, perform optimization tasks, and so
46+
on, the use of uppercase keywords becomes less convenient. Lowercase keywords are easier to type. Finally, constantly
47+
shouting at your database is not a good idea.
48+
49+
At the same time, it might still make sense to use uppercase SQL keywords when using them in, for example, natural
50+
language texts, for example:
51+
52+
> .. using multiple JOINs ..
53+
54+
## 1) Reserved words
55+
56+
Always use lowercase for reserved keywords such as `select`, `where`, or `as`.
57+
58+
## 2) Variable names
59+
60+
1. Use consistent and descriptive identifiers and names.
61+
2. Use lower case names with underscores, such as `first_name`. **Do not use CamelCase.**
62+
3. Functions such as `cardinality()`, `array_agg()`, and `substr()` are
63+
[identifiers](https://postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS) and should
64+
be treated like variable names.
65+
4. Names must begin with a letter and may not end in an underscore.
66+
5. Only use letters, numbers, and underscores in variable names.
67+
68+
## 3) Be explicit
69+
70+
When choosing between explicit or implicit syntax, prefer explicit.
71+
72+
### 3.1) Aliasing
73+
74+
Always include the `as` keyword when aliasing a variable or table name, it's easier to read when explicit.
75+
76+
✅ Good:
77+
78+
```sql
79+
select date(t.created_at) as day
80+
from telemetry as t
81+
limit 10;
82+
```
83+
84+
❌ Bad:
85+
86+
```sql
87+
select date(t.created_at) day
88+
from telemetry t
89+
limit 10;
90+
```
91+
92+
### 3.2) JOINs
93+
94+
Always include the `join` type rather than relying on the default join.
95+
96+
✅ Good:
97+
98+
```sql
99+
select
100+
submission_date,
101+
experiment.key as experiment_id,
102+
experiment.value as experiment_branch,
103+
count(*) as count
104+
from
105+
telemetry.clients_daily
106+
cross join
107+
unnest(experiments.key_value) as experiment
108+
where
109+
submission_date > '2019年07月01日'
110+
and sample_id = '10'
111+
group by
112+
submission_date,
113+
experiment_id,
114+
experiment_branch;
115+
```
116+
117+
❌ Bad:
118+
119+
```sql
120+
select
121+
submission_date,
122+
experiment.key as experiment_id,
123+
experiment.value as experiment_branch,
124+
count(*) as count
125+
from
126+
telemetry.clients_daily,
127+
unnest(key_value) as experiment -- implicit JOIN
128+
where
129+
submission_date > '2019年07月01日'
130+
and sample_id = '10'
131+
group by
132+
1, 2, 3; -- implicit grouping column names
133+
```
134+
135+
### 3.3) Grouping columns
136+
137+
Avoid using implicit grouping column names.
138+
139+
✅ Good:
140+
141+
```sql
142+
select state, backend_type, count(*)
143+
from pg_stat_activity
144+
group by state, backend_type
145+
order by state, backend_type;
146+
```
147+
148+
🆗 Acceptable:
149+
150+
```sql
151+
select
152+
date_trunc('minute', xact_start) as xs_minute,
153+
count(*)
154+
from pg_stat_activity
155+
group by 1
156+
order by 1;
157+
```
158+
159+
❌ Bad:
160+
161+
```sql
162+
select state, backend_type, count(*)
163+
from pg_stat_activity
164+
group by 1, 2
165+
order by 1, 2;
166+
```
167+
168+
## 4) Left-align root keywords
169+
170+
All root keywords should start on the same character boundary.
171+
172+
✅ Good:
173+
174+
```sql
175+
select
176+
client_id,
177+
submission_date
178+
from main_summary
179+
where
180+
sample_id = '42'
181+
and submission_date > '20180101'
182+
limit 10;
183+
```
184+
185+
❌ Bad:
186+
187+
```sql
188+
select client_id,
189+
submission_date
190+
from main_summary
191+
where sample_id = '42'
192+
and submission_date > '20180101';
193+
```
194+
195+
## 5) Code blocks
196+
197+
Root keywords should be on their own line in all cases except when followed by only one dependent word. If there are
198+
more than one dependent words, they should form a column that is left-aligned and indented to the left of the root
199+
keyword.
200+
201+
✅ Good:
202+
203+
```sql
204+
select
205+
client_id,
206+
submission_date
207+
from main_summary
208+
where
209+
submission_date > '20180101'
210+
and sample_id = '42'
211+
limit 10;
212+
```
213+
214+
It's acceptable to include an argument on the same line as the root keyword if there is exactly one argument.
215+
216+
🆗 Acceptable:
217+
218+
```sql
219+
select
220+
client_id,
221+
submission_date
222+
from main_summary
223+
where
224+
submission_date > '20180101'
225+
and sample_id = '42'
226+
limit 10;
227+
```
228+
229+
❌ Bad:
230+
231+
```sql
232+
select client_id, submission_date
233+
from main_summary
234+
where submission_date > '20180101' and (sample_id = '42' or sample_id is null)
235+
limit 10;
236+
```
237+
238+
❌ Bad:
239+
240+
```sql
241+
select
242+
client_id,
243+
submission_date
244+
from main_summary
245+
where submission_date > '20180101'
246+
and sample_id = '42'
247+
limit 10;
248+
```
249+
250+
## 6) Parentheses
251+
252+
If parentheses span multiple lines:
253+
254+
1. The opening parenthesis should end the line.
255+
2. The closing parenthesis should line up under the first character of the line that starts the multi-line construct.
256+
3. Indent the contents of the parentheses one level.
257+
258+
✅ Good:
259+
260+
```sql
261+
with sample as (
262+
select
263+
client_id,
264+
submission_date
265+
from main_summary
266+
where
267+
sample_id = '42'
268+
)
269+
...
270+
```
271+
272+
❌ Bad (terminating parenthesis on shared line):
273+
274+
```sql
275+
with sample as (
276+
select
277+
client_id,
278+
submission_date
279+
from main_summary
280+
where
281+
sample_id = '42')
282+
...
283+
```
284+
285+
❌ Bad (no indent):
286+
287+
```sql
288+
with sample as (
289+
select
290+
client_id,
291+
submission_date
292+
from main_summary
293+
where
294+
sample_id = '42'
295+
)
296+
...
297+
```
298+
299+
## 7) Boolean operators at the beginning of line
300+
301+
"and" and "or" should always be at the beginning of the line.
302+
303+
✅ Good:
304+
305+
```sql
306+
...
307+
where
308+
submission_date > '2018年01月01日'
309+
and sample_id = '42'
310+
```
311+
312+
❌ Bad:
313+
314+
```sql
315+
...
316+
where
317+
submission_date > '2018年01月01日' and
318+
sample_id = '42'
319+
```
320+
321+
## 8) Nested queries
322+
323+
Do not use nested queries. Instead, use common table expressions to improve readability.
324+
325+
✅ Good:
326+
327+
```sql
328+
with sample as (
329+
select
330+
client_id,
331+
submission_date
332+
from main_summary
333+
where
334+
sample_id = '42'
335+
)
336+
select *
337+
from sample
338+
limit 10;
339+
```
340+
341+
❌ Bad:
342+
343+
```sql
344+
select *
345+
from (
346+
select
347+
client_id,
348+
submission_date
349+
from main_summary
350+
from main_summaryain_summary
351+
where
352+
sample_id = '42'
353+
)
354+
limit 10;
355+
```
356+
357+
## About this document
358+
359+
This document is heavily influenced by the [SQL Style Guide](https://www.sqlstyle.guide/)
360+
and [Mozilla SQL Style Guide](https://docs.telemetry.mozilla.org/concepts/sql_style.html). Proposals, extensions, and
361+
fixes are welcome.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /