Thread: How to create crosstab with 3 values in every crosstab column
I'm looking for a way to generate cross tab with 3 columns for every store wherenumber of stores in not hard coded.Every store info should contain 3 columns:turnoverbudgetbudget percent (=turnover/budget*100)Result should look like:Acc st1turnover st1budget st1percent ... stNturnover st1budget stNpercent311 100 200 50 200 ... 300 67312 400 500 80 600 ... 700 86...I tried crosstab from tablefunc but it allows only single value in every crosstabled column.How to show 3 values in every column: sales, budget and percent in this order?Tables are:create table sales (account char(10),store char(10),sales numeric(12,2) );insert into sales values('311','ST1',100)... ('311','STN',200)('312','ST1',400)... ('312','STN',600);create table budget (account char(10),store char(10),budget numeric(12,2) );insert into budger values('311','ST1',200)... ('311','STN',300)('312','ST1',500)... ('312','STN',700);Some account and store values may be missing from tables.Andrus.
Thank you. >first calculate how much columns we should return...No of stores in in your >Sales table (multiply 3 in your case)... >(and based on that - build the grid in UI) >then with knowing that - we select full "table" with simple 3 functions: >CalcSales(coount, Store), getBudget(account, Store) >and then build dynamic query with those 3 functions many times as we have >stores as columns... My goal is to open result En excel. Instead of building dynamic query isn't it reasonable to create csv file directly from code without using crosstab but creating it manually ? It looks that crosstab does not have any advantages instead on manual crosstab creation ? Another possibility is to merge those 3 columns into single column and crosstab it . After that create csv file by splitting single column into 3 columns. Can some postgres array function or something like used to split 1 column into 3 columns in result without building query string manually ? I posted this also in http://stackoverflow.com/questions/9162497/how-to-generate-crosstab-with-3-columns-for-every-store-in-postgresql Andrus.
- loop trough distinict Accounts from Sales Table
- inside Accounts loop,
- WriteToFile(Account), then loop trough distinct Stores from Sales Table
- inside Stores Loop
- WriteToFile(';' + Store)
- WriteToFile(';' + calcSales(acount, Store)
- WriteToFile(';' + getBudget(acount, Store)
- WriteToFile(';' + calcPercent(acount, Store)
- after Stores loop make new line in file
- and after Accounts loop close the file..
Thank you.My goal is to open result En excel.first calculate how much columns we should return...No of stores in in your
Sales table (multiply 3 in your case)...
(and based on that - build the grid in UI)
then with knowing that - we select full "table" with simple 3 functions:
CalcSales(coount, Store), getBudget(account, Store)
and then build dynamic query with those 3 functions many times as we have
stores as columns...
Instead of building dynamic query isn't it reasonable to create csv file
directly from code without using crosstab
but creating it manually ?
It looks that crosstab does not have any advantages instead on manual
crosstab creation ?
Another possibility is to merge those 3 columns into single column and
crosstab it .
After that create csv file by splitting single column into 3 columns.
Can some postgres array function or something like used to split 1 column
into 3 columns in result without
building query string manually ?
I posted this also in
http://stackoverflow.com/questions/9162497/how-to-generate-crosstab-with-3-columns-for-every-store-in-postgresql
Andrus.
Thank you. > the point is - it is not possible to get unknown no of columns in 1 SQL > query... >i.e. >Account, Store, Amount >100, St1, 1000.00 >100, St2, 2000.00 >to get: >Acount, St1 , St2 >100, 1000.00 2000.00 >to get that in your query... St1 and St2 - must be hardcoded... (is there 1 >column per Store, or 3 columns per store it >is less important...) >if it St1 and St2 are hardcoded in query, even if in table is: >Account, Store, Amount >100, St1, 1000.00 >100, St2, 2000.00 >100, St3, 3000.00 >We would get the same result...actually if we want St3 we need to change >our query and add St3 in it... >that is the reason why we use Dynamic SQL to build the query... >when you build your Dynamic SQL query... you could use COPY (dynamicQuery) >TO CSV file... >or instead of to build dynamic query, you can export directly to file... I din't knwo this. This seems very serious limitation which makes crosstab useless . I tried create temp table sales ( account char(10), store char(10), sales numeric(12,2) ) on commit drop; insert into sales values ('311','ST1',100), ('311','STN',200), ('312','ST1',400), ('312','STN',600); select * from crosstab('select * from sales', 'select distinct store from sales' ) x and got error ERROR: a column definition list is required for functions returning "record" Can we use something like select * from dynamicwrapper( crosstab('select * from sales', 'select distinct store from sales' )) x Where to find generic dynamicwrapper stored procedure which fixes this by building dynamic query itself or other idea ? Andrus.
Thank you.I din't knwo this. This seems very serious limitation which makes crosstab useless .the point is - it is not possible to get unknown no of columns in 1 SQL query...
i.e.
Account, Store, Amount
100, St1, 1000.00
100, St2, 2000.00
to get:
Acount, St1 , St2
100, 1000.00 2000.00
to get that in your query... St1 and St2 - must be hardcoded... (is there 1 column per Store, or 3 columns per store it >is less important...)
if it St1 and St2 are hardcoded in query, even if in table is:
Account, Store, Amount
100, St1, 1000.00
100, St2, 2000.00
100, St3, 3000.00
We would get the same result...actually if we want St3 we need to change our query and add St3 in it...
that is the reason why we use Dynamic SQL to build the query...
when you build your Dynamic SQL query... you could use COPY (dynamicQuery) TO CSV file...
or instead of to build dynamic query, you can export directly to file...
I tried
create temp table sales (
account char(10),
store char(10),
sales numeric(12,2) ) on commit drop;
insert into sales values
('311','ST1',100), ('311','STN',200),
('312','ST1',400), ('312','STN',600);
select * from
crosstab('select * from sales', 'select distinct store from sales' ) x
and got error
ERROR: a column definition list is required for functions returning "record"
Can we use something like
select * from
dynamicwrapper( crosstab('select * from sales', 'select distinct store from sales' )) x
Where to find generic dynamicwrapper stored procedure which fixes this by building dynamic query itself or other idea ?
Andrus.
Hello,
as you don't seems to need the returned column definition in Postgres, a solution may be to cast the result to text.
e.g.:
create or replace function get_record ()
returns setof text as
$$
select (foo)::text from
(values(1,'a a'),(3,'b b'))foo
$$
language sql;
select trim(r,'\\(\\)') from get_record () r;
regards,
Marc Mamin
From: pgsql-general-owner@postgresql.org [mailto:pgsql-general-owner@postgresql.org] On Behalf Of Misa Simic
Sent: Montag, 6. Februar 2012 19:52
To: Andrus
Cc: pgsql-general@postgresql.org
Subject: Re: [GENERAL] How to create crosstab with 3 values in every crosstab column
Hi,
Well, I think you will need to write your own function(s) which will solve your particular case...
There are two ways explaind in last mails... Dynamic SQL or direct export to file...
Kind Regards,
Misa
2012/2/6 Andrus <kobruleht2@hot.ee>
Thank you.
the point is - it is not possible to get unknown no of columns in 1 SQL query...
i.e.
Account, Store, Amount
100, St1, 1000.00
100, St2, 2000.00
to get:
Acount, St1 , St2
100, 1000.00 2000.00
to get that in your query... St1 and St2 - must be hardcoded... (is there 1 column per Store, or 3 columns per store it >is less important...)
if it St1 and St2 are hardcoded in query, even if in table is:
Account, Store, Amount
100, St1, 1000.00
100, St2, 2000.00
100, St3, 3000.00
We would get the same result...actually if we want St3 we need to change our query and add St3 in it...
that is the reason why we use Dynamic SQL to build the query...
when you build your Dynamic SQL query... you could use COPY (dynamicQuery) TO CSV file...
or instead of to build dynamic query, you can export directly to file...
I din't knwo this. This seems very serious limitation which makes crosstab useless .
I tried
create temp table sales (
account char(10),
store char(10),
sales numeric(12,2) ) on commit drop;
insert into sales values
('311','ST1',100), ('311','STN',200),
('312','ST1',400), ('312','STN',600);
select * from
crosstab('select * from sales', 'select distinct store from sales' ) x
and got error
ERROR: a column definition list is required for functions returning "record"
Can we use something like
select * from
dynamicwrapper( crosstab('select * from sales', 'select distinct store from sales' )) x
Where to find generic dynamicwrapper stored procedure which fixes this by building dynamic query itself or other idea ?
Andrus.