I have over 50 different tables which I would like to combine into one big table. All the tables have a different number of columns.
Currently, to union the tables together, I am writing an individual select statement for each of the tables, and inserting a null column if that column doesn't exist in the table. Then I am using UNION ALL to union them together.
For example:
(
select col1
, null as col2
, col3
from table1
union all
select col1
, col2
, null as col
from table2
)
Although this works, it is very manual and time consuming. Is there a better, more efficient way to union these tables into one? As with over 50 tables, I am going to have thousands of lines of code.
Thank you!
You can query SQL Server metadata, and from the result dynamically construct a SQL statement. This can be done in any programming language, including T-SQL itself.
Here's a rough example; execute this query, copy/paste the result back into the query window, and execute that.
If the 50 tables have similar names (e.g. all start with Foo
), then you can replace the exhaustive table list (WHERE TABLE_NAME IN ('table1', 'table2', 'table3')
in my example) by WHERE TABLE_NAME LIKE 'Foo%'
.
WITH
AllTables (TABLE_NAME) AS (
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME IN ('table1', 'table2', 'table3')
),
TablesWithSelectors (TABLE_NAME, COLUMN_NAME, Selector) AS (
SELECT t.TABLE_NAME, a.COLUMN_NAME, CASE WHEN b.COLUMN_NAME IS NULL THEN 'NULL AS ' ELSE '' END + a.COLUMN_NAME
FROM AllTables t
CROSS JOIN (SELECT DISTINCT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME IN (SELECT TABLE_NAME FROM AllTables)) a
LEFT OUTER JOIN INFORMATION_SCHEMA.COLUMNS b ON b.TABLE_NAME = t.TABLE_NAME AND b.COLUMN_NAME = a.COLUMN_NAME
),
SelectStatements (Sql) AS (
SELECT
'SELECT ' +
STUFF((
SELECT ', ' + Selector
FROM TablesWithSelectors
WHERE TABLE_NAME = r.TABLE_NAME
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
, 1, 2, '') +
' FROM ' +
TABLE_NAME
FROM TablesWithSelectors r
GROUP BY TABLE_NAME
)
SELECT STUFF((
SELECT ' UNION ALL ' + sql
FROM SelectStatements
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)'), 1, 11, '')
Thanks to: How to use GROUP BY to concatenate strings in SQL Server?