2012-05-29 45 views
0

我有這個表其他一些列一起:從表中的行創建兩個colums

months amount 
----------------- 
Jan  100 
Feb  200 
Jan  400 

我想,這樣它是這樣來創建此表的視圖:

Jan Feb 
-------------------- 
100 200 
400 0 

我搜索了它,並得到PL/SQL解決方案不能完成只有SQL查詢? 謝謝

+0

您使用的是什麼版本的SQL?如果您知道列和2008+,則可以使用此http://msdn.microsoft.com/zh-cn/library/ms177410(v=sql.105).aspx –

+0

實際上它適用於PostgreSQL – HakimuddinHussain

+0

http:// www .postgresql.org/docs/9.1/static/tablefunc.html - Crosstab是否可用? –

回答

1

首先確保,您有可用交叉

CREATE EXTENSION tablefunc; 

爲了得到你想要的交叉表至少需要三列

如:

name months amount 
------------------------- 
Helga Jan  100 
Helga Feb  200 
Bernd Jan  400 

然後創建你的Crosstable是這樣的:

SELECT * FROM 
    crosstab('SELECT name, month, amount from temp') 
AS ct(name varchar, jan int, feb int); 

name  jan  feb 
-------------------------- 
Helga  100  200 
Bernd  400 

如果你將不得不列每個月,堅持例子作爲manual

create table sales(year int, month int, qty int); 
insert into sales values(2007, 1, 1000); 
insert into sales values(2007, 2, 1500); 
insert into sales values(2007, 7, 500); 
insert into sales values(2007, 11, 1500); 
insert into sales values(2007, 12, 2000); 
insert into sales values(2008, 1, 1000); 

select * from crosstab(
    'select year, month, qty from sales order by 1', 
    'select m from generate_series(1,12) m' 
) as (
    year int, 
    "Jan" int, 
    "Feb" int, 
    "Mar" int, 
    "Apr" int, 
    "May" int, 
    "Jun" int, 
    "Jul" int, 
    "Aug" int, 
    "Sep" int, 
    "Oct" int, 
    "Nov" int, 
    "Dec" int 
); 
year | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec 
------+------+------+-----+-----+-----+-----+-----+-----+-----+-----+------+------ 
2007 | 1000 | 1500 |  |  |  |  | 500 |  |  |  | 1500 | 2000 
2008 | 1000 |  |  |  |  |  |  |  |  |  |  | 
(2 rows) 
1

說明沒有與你的邏輯出了問題,怎麼會SQL知道它應該是

Jan  Feb 
100  200 
400  0 

,而不是

Jan  Feb 
400  200 
100  0 

我已經採取這意味着列應以升序排列,(除FO r其中的值是0,因爲沒有足夠的數據):

WITH CTE AS 
( SELECT Month, Amount, ROW_NUMBER() OVER(PARTITION BY Month ORDER BY Amount) AS RowNumber 
    FROM T 
) 
SELECT COALESCE(Jan.Amount, 0) AS Jan, 
     COALESCE(Feb.Amount, 0) AS Feb, 
     COALESCE(Mar.Amount, 0) AS Mar 
FROM ( SELECT RowNumber, Amount 
      FROM CTE 
      WHERE Month = 'Jan' 
     ) jan 
     FULL JOIN 
     ( SELECT RowNumber, Amount 
      FROM CTE 
      WHERE Month = 'Feb' 
     ) feb 
      ON feb.RowNumber = Jan.RowNumber 
     FULL JOIN 
     ( SELECT RowNumber, Amount 
      FROM CTE 
      WHERE Month = 'Mar' 
     ) Mar 
      ON Mar.RowNumber = Jan.RowNumber 

這一邏輯已經SQL Fiddle過測試,但我相當肯定,你可以申請使用ROWNUMBER來交叉來解決你的問題目前正與CROSSTAB合作。 ROWNUMBER成爲你rowvalue,我從來沒有使用交叉表中Postgres的,但我認爲你會落得這樣的:

SELECT * 
FROM CROSSTAB('SELECT ROW_NUMBER() OVER(PARTITION BY Month ORDER BY Amount) AS RowNumber, Month, Amount FROM T', 
       'SELECT DISTINCT ROW_NUMBER() OVER(PARTITION BY Month ORDER BY Amount) AS RowNumber FROM T') 
     AS (RowNumber INT, Jan INT, Feb INT, Mar INT); 

我不能得到這個工作的SQL小提琴,但我認爲這是因爲CROSSTAB ISN因爲即使Postgres文檔中的示例在SQL Fiddle上也不起作用。

+1

順便說一句 - 我剛剛添加交叉表函數到sql小提琴。 –