GROUP BY, UNION ALL, etc. incompatible with "river"
emlazzarin opened this issue · 1 comments
SELECT one,
two,
three,
five
FROM some_table
INNER JOIN (SELECT five,
six,
seven
FROM another_table
WHERE field = 'special'
GROUP BY 1
UNION ALL
SELECT five,
eight,
nine
FROM third_table
WHERE something > 2
GROUP BY 1)
USING (five)
WHERE field = 'default'
GROUP BY 1, 2
Please see the inner GROUP BY
statements and the UNION ALL
: is this the recommended style? It preserves the river, but at the cost of the GROUP BY
and UNION ALL
"overflowing" left of the open parentheses, violating the alignment. One possible fix is to add space to the left side of the subquery:
SELECT one,
two,
three,
five
FROM some_table
INNER JOIN ( SELECT five,
six,
seven
FROM another_table
WHERE field = 'special'
GROUP BY 1
UNION ALL
SELECT five,
eight,
nine
FROM third_table
WHERE something > 2
GROUP BY 1)
USING (five)
WHERE field = 'default'
GROUP BY 1, 2
Another fix is to simply move the entire subquery left, breaking alignment with the parentheses:
SELECT one,
two,
three,
five
FROM some_table
INNER JOIN (
SELECT five,
six,
seven
FROM another_table
WHERE field = 'special'
GROUP BY 1
UNION ALL
SELECT five,
eight,
nine
FROM third_table
WHERE something > 2
GROUP BY 1)
USING (five)
WHERE field = 'default'
GROUP BY 1, 2
I would tend to lay it out so that the GROUP
keyword is west of the river and BY
is east of the river. Having just reviewed similar queries in Celko's books again this is the style he uses as well. In fact I think I might add some information to the guide to document GROUP BY
.
So using some of your example code we could lay it out like so:
SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2
I like this because GROUP
is really enough to spot that particular part of the statement when scanning to the west of the river as you read a query.
Now onto your other issue with UNION
or UNION ALL
; I tend to treat these as exceptions (like jokers in a pack of playing cards) as they're outside the query in question generally. I put them on a new line with clear whitespace surrounding them so it is quick and easy to see where the queries end and begin. I've used the shortened version of your code from above to illustrate this below:
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
UNION ALL
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
Celko does put them on their own line and he ignores the river for a UNION ALL
, but he dispenses with the extra surrounding whitespace lines I have included above. So for the above query he might write:
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
UNION ALL
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
I find the UNION ALL
a little jarring in this final example as it ignores the river without any leading or following whitespace to help negate the effect of non-conformity.
A further option would be to take the lead of the GROUP BY
we discussed earlier:
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
UNION ALL
(SELECT one,
two,
three,
five
FROM some_table
WHERE field = 'default'
GROUP BY 1, 2)
This is probably the one that makes the most sense given that the keyword is really UNION
and ALL
is but a modifier to it.
I am thinking that adding a few, more complicated, SQL examples to the guide might help to cover off some of these more advanced usages and their optimal layout.