简体   繁体   中英

SQL table names as variable

Is there a better way to write the following SQL :

select item, price, 'Global Sales' as source_table from global_sales
union all
select item, price, 'Regional Sales' as source_table from regional_sales
union all
select item, price, 'Local Sales' as source_table from local_sales

I have more than 20 tables to union but wondering whether there is a more efficient way to write this sql. Finally I want to use the SQL as a view.

This sort of query is indicative of poor table design.

For the short term, you can write a little program to do the repetitive work for you. Here's an example in Ruby.

#!/usr/bin/env ruby

tables = [
  'global_sales',
  'regional_sales',
  'local_sales'
]

def table2column(table)
  return table.split('_')
    .map { |word| word[0].upcase!; word }
    .join(" ")
end

puts tables.map { |table|
  column = table2column(table)
  "select item, price, '#{column}' from #{table}\n"
}.join("union all\n")

Lets just assume we have all the sales are categorized due to difference in items offered for sales depending on locations.

Your table design can be improved. If all the rest of the data are equal, all sales can be stored in a single table with the narrowest possible location.

create table sales (
    id integer primary key,
    item integer references items(id),
    price numeric(10,2) not null,
    location integer references locations(id)
);

create table locations (
     id integer primary key,
     name text,
     ... etc ...
);

And a table to specify what region each location is in.

create table regions (
     id integer primary key,
     name text,
     ... etc ...
);

create table regional_locations (
     id integer primary key,
     location integer references locations(id),
     region integer references regions(id)
);

Then getting global sales is easy.

select item, price from sales;

And sales for one region can be had.

select item, price, r.name, l.name
from sales s
-- Get the region for each location
join regional_locations rl on rl.location = s.location
 -- Get the region name
 and regions r on rl.region = r.id
 -- Get the location name
 and locations l on s.location = l.id
where rl.region = ?

For backwards compatibility, each old table becomes a view. For example...

create view global_sales
    select id, item, price from sales;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM