CREATE TABLE tb2 AS
SELECT c1, c2, c3
FROM tb1
WHERE c1 = '1'
AND c3 <> ''
UNION ALL
SELECT c1, c2, c4
FROM tb1
WHERE c1 = '1'
AND c4 <> '';
- Use
UNION ALL
unless you want to eliminate possible duplicates. Faster. The result is different if duplicates occur!
- No need for a subquery.
- Use
CREATE TABLE AS
instead of SELECT INTO
. Per documentation:
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
.
- The single quotes around
'1'
indicate you are storing numeric data as string type. If so, that's not good. Consider appropriate data types ...
Alternative with CTE
If the table is big, this alternative with a CTE will be probably be faster, since we only read once from it.
Also including additional requests from comment, add column, add pk:
CREATE TABLE tb2 AS
WITH cte AS (
SELECT c1, c2, c3, c4
FROM tb1
WHERE c1 = '1'
AND (c3 <> '' OR c4 <> '')
)
SELECT c1, c2, c3, NULL::text AS new_column -- add new column
FROM cte
WHERE c3 <> ''
UNION ALL
SELECT c1, c2, c4, NULL
FROM cte
WHERE c4 <> '';
-- add primary key:
ALTER TABLE tb2 ADD CONSTRAINT tb2_pkey PRIMARY KEY(???);
If the table is big, you might want to increase temp_buffers
setting (for the session only). More info in this related answer:
How to delete duplicate entries?
If you need to run this often (and don't mind the small penalty on write opertaions), and if you can define a superset of rows that eliminates large parts of the rest, I would suggest a partial index ...