I am working on a project where each user is assigned to its own schema, which looks like this:
user_537 (schema)
posts (table)
likes (table)
actions (table)
user_538 (schema)
posts (table)
likes (table)
actions (table)
user_539 (schema)
posts (table)
likes (table)
actions (table)
Now I want to query across every actions
table. I would like to get the result of:
select
537 as user_id,
count(*) actions
from actions
UNION ALL
select
538 as user_id,
count(*) actions
from actions
UNION ALL
select
539 as user_id,
count(*) actions
from actions
UNION ALL
How can I do that without manually typing all schemas? For now I only managed to create a select
that I can run to get what I want:
SELECT distinct 'SELECT ' || REPLACE(table_schema, 'user', '' ) || ' as user_id, count(*) as actions FROM ' || table_schema || '.actions UNION ALL' AS query
FROM information_schema.tables
where table_schema like '%user%'
But I dont like this for 2 reasons:
- I have to manually copy output query to run it again
- I have additional
UNION ALL
at the and which I have to manually remove
Instead of this I would like to have a query that iterate over each schema, run a code and unions
the result.
3
Answers
You should not have "many same schemas".
(Either that, or you should not be working on that project.)
You should have only one schema where each record in each table also contains the user id.
That’s the way relational databases are done.
If unsure about relational database fundamentals, then a good starting point would be Wikipedia (https://en.wikipedia.org/wiki/Relational_database)
Look for subjects like "normalization" and "denormalization" and you will understand exactly why having "many same schemas" is terribly, terribly wrong, and why if you do this you paint yourself into a corner and you cannot proceed any further.
It would not hurt to read a few good books on the subject, or take a course, before attempting to program relational databases.
As pointed out, your database design should be revised (normalized), but as it is now you could generate your query like this:
Implemented as a function is:
and then to execute
The following query gets the counts for
actions
,likes
, andposts
across schemas:If only the
actions
counts are required, then the query can be simplified to use a singleXPATH
: