CREATE TABLE AS vs SELECT INTO

Without the explanation, always use CREATE TABLE AS without exception. At the bottom of each under NOTES this is cleared up,

Notes for SELECT INTO,

CREATE TABLE AS is functionally similar to SELECT INTO. CREATE TABLE AS is the recommended syntax, since this form of SELECT INTO is not available in ECPG or PL/pgSQL, because they interpret the INTO clause differently. Furthermore, CREATE TABLE AS offers a superset of the functionality provided by SELECT INTO.

Notes for CREATE TABLE AS,

This command is functionally similar to SELECT INTO, but it is preferred since it is less likely to be confused with other uses of the SELECT INTO syntax. Furthermore, CREATE TABLE AS offers a superset of the functionality offered by SELECT INTO.

Also in the Compatibility section of the docs of SELECT INTO it goes even further,

The SQL standard uses SELECT INTO to represent selecting values into scalar variables of a host program, rather than creating a new table. This indeed is the usage found in ECPG (see Chapter 34) and PL/pgSQL (see Chapter 41). The PostgreSQL usage of SELECT INTO to represent table creation is historical. It is best to use CREATE TABLE AS for this purpose in new code.

So we have,

  1. PostgreSQL thinks it's confusing because SELECT INTO does other stuff in contexts only available in PL/pgSQL, and ECPG.
  2. CREATE TABLE supports more functionality (I assume they're referring to WITH OIDS, and TABLESPACE, IF NOT EXISTS).
  3. SELECT INTO for table creation is "deprecated".

As a side note, the syntax for a CTAS with a CTE may look a bit weird., and SELECT INTO may also be some kind of hold over QUEL's RETRIEVE INTO. QUEL was the predecessor to SQL, that the predecessor to PostgreSQL (INGRES) used.