Joshua Burns
Joshua Burns

Reputation: 8572

Dynamic table name in PostgreSQL

I have a situation where multiple tables contain similar information based on country. Changing the database schema is not an option, I'm not interested in the use of a stored procedure. I'd prefer to grab everything in a single query returning multiple rows than performing one query for every country.

First, I have a definitions table which lists all the countries we have tables for:

countries
+============+========+
| country_id | prefix |
+============+========+
| 1          | us     |
+------------+--------+
| 2          | ca     |
+------------+--------+

Secondly, I have a relationships table:

relationships
+========+============+==============+
| rel_id | country_id | upc          |
+========+============+==============+
| 1      | 1          | 111111111111 |
+--------+------------+--------------+
| 2      | 2          | 111111111111 |
+--------+------------+--------------+
| 3      | 1          | 222222222222 |
+--------+------------+--------------+
| 4      | 2          | 222222222222 |
+--------+------------+--------------+
| 5      | 2          | 333333333333 |
+--------+------------+--------------+
| 6      | 1          | 444444444444 |
+--------+------------+--------------+

Then, I have two tables named "us_products" and "ca_products". If an entry exists in the countries table, then a table exists with the name [countries.prefix]_products. All *_products tables are identical to one another. Same columns and same data types.

us_products
+============+==============+=======+
| product_id | upc          | title |
+============+==============+=======+
| 1          | 111111111111 | Shoe! |
+------------+--------------+=======+
| 2          | 222222222222 | Tie   |
+------------+--------------+=======+
| 3          | 444444444444 | Sock  |
+------------+--------------+=======+

ca_products
+============+==============+=======+
| product_id | upc          | title |
+============+==============+=======+
| 1          | 111111111111 | Shoe. |
+------------+--------------+=======+
| 2          | 222222222222 | Tie   |
+------------+--------------+=======+
| 3          | 333333333333 | Shirt |
+------------+--------------+=======+

The goal is to have a query formatted something similar to the following (obviously this doesn't work, otherwise I wouldn't be asking this question...):

SELECT
  countries.prefix,
  products.title
FROM
  relationships
INNER JOIN
  [countries.prefix]_products AS products
  ON
  relationships.upc = products.upc
WHERE
  relationships.upc = '111111111111'

Should return:

+========+=======+
| prefix | title |
+========+=======+
| us     | Shoe! |
+--------+-------+
| ca     | Shoe. |
+--------+-------+

Thanks for the help! If the ONLY way of doing this is through a stored procedure then I supposed I don't have any other option, in which case would you mind throwing together an example procedure and query which would perform on the above mentioned table structures?

Upvotes: 0

Views: 1009

Answers (1)

user330315
user330315

Reputation:

If you don't want to create a view, you can use a common table expression as a "temporary" view:

with normalized_products as (
   select 1 as country_id, 
          product_id, 
          upc,
          title 
   from us_products
   union all
   select 2 as country_id, 
          product_id, 
          upc,
          title 
   from ca_products
) 
SELECT countries.prefix,
       products.title
FROM relationships as rel
  JOIN normalized_products as prod
    ON rel.upc = prod.upc
   and rel.country_id = prod.country_id
where rel.upc = '111111111111'

But again: do fix your datamodel. This is going to hurt you more and more

Upvotes: 3

Related Questions