I have a unique situation where all tables in a database will have the same columns and data types, yet must be kept as separate tables.
I'd like to write a query that can find all of those tables and join them, preferably with one column that identifies the source table. I need it to find all the tables, rather than specify them, as they will change over time and re-writing this query is likely to be a nuisance.
Is this possible?
To illustrate:
database: all_data
table: red
columns: date text, value numeric, notes text
table: green
columns: date text, value numeric, notes text
... etc etc
The output would be:
source: date: value: notes:
red 9/24 12 good
red 9/23 1 review
green 9/21 -1 fail
green 9/10 100 excellent
CodePudding user response:
You can make a Dynamic query, like this:
You have to filter using the correct table_schema.
SELECT
regexp_replace(string_agg('SELECT ''' || table_name || ''' AS source, date, value, notes FROM ' || table_name || ' UNION ALL ', ' '), ' UNION ALL $', ';') AS "query"
FROM information_schema.tables
WHERE table_schema = 'public';
Example output:
SELECT 'red' AS source, date, value, notes FROM red
UNION ALL
SELECT 'green' AS source, date, value, notes FROM green;
Creating a PL/pgSQL function (It is an example, maybe you can improve it):
CREATE FUNCTION getAllTablesRows() RETURNS TABLE(source text, date text, value numeric, notes text) AS
$$
DECLARE
cursorTables CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
BEGIN
FOR tableName IN cursorTables LOOP
RETURN QUERY EXECUTE format('SELECT %L::text AS source, date, value, notes FROM %I', tableName.table_name, tableName.table_name);
END LOOP;
END;
$$ LANGUAGE 'plpgsql';
Calling it:
SELECT * FROM getAllTablesRows();