diff --git a/sql_style_guide.md b/sql_style_guide.md
index c25be50..9123ae1 100644
--- a/sql_style_guide.md
+++ b/sql_style_guide.md
@@ -2,10 +2,10 @@
- [General guidelines](#general-guidelines)
- [Syntax](#syntax)
- - [Aliases](#aliases)
- [Joins](#joins)
- [Case statements](#case-statements)
- [CTEs](#ctes)
+ - [Naming](#naming)
- [Formatting](#formatting)
- [Credits](#credits)
@@ -98,6 +98,32 @@ from customers
+#### Always use the `as` keyword when aliasing columns, expressions, and tables.
+```sql
+/* Good */
+select count(*) as customers_count
+from customers
+
+/* Bad */
+select count(*) customers_count
+from customers
+```
+
+
+
+#### Always alias grouping aggregates and other column expressions.
+```sql
+/* Good */
+select max(id) as max_customer_id
+from customers
+
+/* Bad */
+select max(id)
+from customers
+```
+
+
+
#### Use `where` instead of `having` when either would suffice.
Queries filter on the `where` clause earlier in their processing, so `where` filters are more performant.
@@ -201,78 +227,6 @@ where email like '''%@domain.com'''
-### Aliases
-
-#### Always use the `as` keyword when aliasing columns, expressions, and tables.
-```sql
-/* Good */
-select count(*) as customers_count
-from customers
-
-/* Bad */
-select count(*) customers_count
-from customers
-```
-
-
-
-#### Always alias grouping aggregates and other column expressions.
-```sql
-/* Good */
-select max(id) as max_customer_id
-from customers
-
-/* Bad */
-select max(id)
-from customers
-```
-
-
-
-#### Date/time column aliases:
- - Date columns based on UTC should be named like `_date`.
- - Date columns based on a specific timezone should be named like `_date_` (e.g. `order_date_et`).
- - Date+time columns based on UTC should be named like `_at`.
- - Date+time columns based on a specific timezone should be named like `_at_` (e.g `created_at_pt`).
- - US timezone indicators:
- - `et` = Eastern Time.
- - `ct` = Central Time.
- - `mt` = Mountain Time.
- - `pt` = Pacific Time.
-
-
-
-#### Boolean column aliases:
- - Boolean columns should be prefixed with a present or past tense third-person singular verb, such as:
- - `is_` or `was_`.
- - `has_` or `had_`.
- - `does_` or `did_`.
-
-
-
-#### Avoid using unnecessary table aliases, especially initialisms.
-Suggested guidelines:
- - If the table name consists of 3 words or less don't alias it.
- - Use a subset of the words as the alias if it makes sense (e.g. if `partner_shipments_order_line_items` is the only line items table being referenced it could be reasonable to alias it as just `line_items`).
-
-```sql
-/* Good */
-select
- customers.email
- , orders.invoice_number
-from customers
-inner join orders on customers.id = orders.customer_id
-
-/* Bad */
-select
- c.email
- , o.invoice_number
-from customers as c
-inner join orders as o on c.id = o.customer_id
-```
-
-
-
### Joins
#### Don't use `using` in joins.
@@ -607,6 +561,80 @@ from (
+## Naming
+
+#### Name single-column primary keys `id`.
+This allows us to easily tell at a glance whether a column is a primary key, helps us [discern whether joins are one-to-many or many-to-one](#in-join-conditions-put-the-table-that-was-referenced-first-immediately-after-on), and is more succinct than other primary key naming conventions (particularly in join conditions).
+
+```sql
+/* Good */
+select ...
+from orders
+left join customers on orders.customer_id = customers.id
+/* Easier to tell this is a many-to-one join and thus won't fan out. */
+
+/* Bad */
+select ...
+from orders
+left join customers on orders.customer_id = customers.customer_id
+
+/* Good */
+select ...
+from orders
+left join some_exceedingly_long_name on orders.some_exceedingly_long_name_id = some_exceedingly_long_name.id
+
+/* Bad */
+select ...
+from orders
+left join some_exceedingly_long_name on orders.some_exceedingly_long_name_id = some_exceedingly_long_name.some_exceedingly_long_name_id
+```
+
+
+
+#### Date/time column names:
+ - Date columns based on UTC should be named like `_date`.
+ - Date columns based on a specific timezone should be named like `_date_` (e.g. `order_date_et`).
+ - Date+time columns based on UTC should be named like `_at`.
+ - Date+time columns based on a specific timezone should be named like `_at_` (e.g `created_at_pt`).
+ - US timezone indicators:
+ - `et` = Eastern Time.
+ - `ct` = Central Time.
+ - `mt` = Mountain Time.
+ - `pt` = Pacific Time.
+
+
+
+#### Boolean column names:
+ - Boolean columns should be prefixed with a present or past tense third-person singular verb, such as:
+ - `is_` or `was_`.
+ - `has_` or `had_`.
+ - `does_` or `did_`.
+
+
+
+#### Avoid using unnecessary table aliases, especially initialisms.
+Suggested guidelines:
+ - If the table name consists of 3 words or less don't alias it.
+ - Use a subset of the words as the alias if it makes sense (e.g. if `partner_shipments_order_line_items` is the only line items table being referenced it could be reasonable to alias it as just `line_items`).
+
+```sql
+/* Good */
+select
+ customers.email
+ , orders.invoice_number
+from customers
+inner join orders on customers.id = orders.customer_id
+
+/* Bad */
+select
+ c.email
+ , o.invoice_number
+from customers as c
+inner join orders as o on c.id = o.customer_id
+```
+
+
+
## Formatting
An overarching pattern is: