Derived column lists are a fine feature, if your database supports them. The SQL:2008 standard specifies
7.6 <table reference> <table reference> ::= <table factor> | <joined table> <table factor> ::= <table primary> [ <sample clause> ] <table primary> ::= <table or query name> [ [ AS ] <correlation name> [ <left paren> <derived column list> <right paren> ] ] | <derived table> [ AS ] <correlation name> [ <left paren> <derived column list> <right paren> ] | [...]
When you put this in action in an actual query, the above becomes (in Postgres SQL):
SELECT t.a, t.b FROM ( SELECT 1, 2 ) t(a, b)
In words: You can rename a derived table AND its columns in a single step, by supplying a <derived column list> to your <correlation name> (also known as table alias). The main advantage of this syntax is the fact that you only need to know the degree of your derived table, not the concrete (possibly auto-generated) names of its columns. This is particularly useful when renaming columns from an unnested table or from a table or array function:
SELECT t.a, t.b FROM unnest(my_table_function()) t(a, b)
Simulating derived column lists
Not all databases support <derived column lists> along with a <correlation name>. But you can always simulate them. The simplest way is to use common table expressions. In Oracle, for instance, you could rewrite the above Postgres SQL statement to this:
-- Postgres SELECT t.a, t.b FROM ( SELECT 1, 2 ) t(a, b) -- Equivalent Oracle query WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) SELECT * FROM t -- Or a bit more verbose, if you really want to hide the -- common table expression within the derived table SELECT t.a, t.b FROM ( WITH t(a, b) AS ( SELECT 1, 2 FROM DUAL ) SELECT * FROM t ) t
Note that the CTE solution was given on this Stack Overflow question:
http://stackoverflow.com/q/14127707/521799
If your database supports neither derived column lists, nor common table expressions, you will have to push down the derived column list into the derived table and transform your nested SQL. In MySQL or H2, the above Postgres query would look like this:
-- MySQL, H2, and others SELECT t.a, t.b FROM ( SELECT 1 a, 2 b ) t
It looks simple, but of course you’ll have to be able to actually transform your nested select and other sorts of table references
The solution to rule them all
If the latter isn’t an option for you, here’s one that will always work:
-- All databases SELECT t.a, t.b FROM ( SELECT null a, null b FROM DUAL WHERE 1 = 0 UNION ALL SELECT 1, 2 FROM DUAL ) t
Just concatenate an empty record in front of your actual query, which imposes column names upon your UNION ALL query. Thanks go to Bill’s great answer on Stack Overflow
Filed under: sql Tagged: aliasing, Common Table Expressions, cte, derived column list, postgres sql, sql, sql standard, table expressions Image may be NSFW.
Clik here to view.
Clik here to view.
