Reputation: 91
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.
Upvotes: 0
Views: 74
Reputation: 164679
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;
Upvotes: 1