2017-05-08 108 views
0

我有一個名爲payment_info的表,並帶有以下記錄。postgresql - 將單行更改爲多行

paymentid | customercode | previousbalance | paymentamount | remainingbalance 
----------------------------------------------------------------------------- 
PID0001 | CUST024 | 10000  |  2500  | 7500 
PID0002 | CUST031 | 8500   |  3500  | 5000 
PID0003 | CUST005 | 12000  |  1500  | 10500 

然後,我想要的是創建一個3行上述表中的每行。 我希望我的結果看起來像這樣。

Payment Group | Payment Line Item | Payment ID | Customer Code |  Type   | Amount  
-------------------------------------------------------------------------------------------------- 
    1   |   1   | PID0001 | CUST024  | PREVIOUS BALANCE | 10000.00  
    1   |   2   |   |    | PAYMENT AMOUNT  | 2500.00  
    1   |   3   |   |    | REMAINING BALANCE | 7500.00  

    2   |   1   | PID0002 | CUST031  | PREVIOUS BALANCE | 8500.00  
    2   |   2   |   |    | PAYMENT AMOUNT  | 3500.00  
    2   |   3   |   |    | REMAINING BALANCE | 5000.00  

    3   |   1   | PID0003 | CUST005  | PREVIOUS BALANCE | 12000.00  
    3   |   2   |   |    | PAYMENT AMOUNT  | 1500.00  
    3   |   3   |   |    | REMAINING BALANCE | 10500.00  

這是我開始的查詢。但它沒有返回與上面相同的結果。

select row_number() over() as id,paymentid,customercode,'PREVIOUS BALANCE' as type,previousbalance from payment_info 
union 
select row_number() over() as id,'','','PAYMENT AMOUNT' as type,paymentamount from payment_info 
union 
select row_number() over() as id,'','','REMAINING BALANCE' as type,remainingbalance from payment_info 

有沒有其他方法,我不會使用UNION關鍵字?因爲在真正的表格中,我將使用30多列,查詢數千條記錄。

我也不知道如何從付款組(每個付款ID)和付款行項目(每個組)創建自動生成號碼(ID)。

感謝

+0

使用** UNION ALL **,它以低於UNION的成本自行返回所有行。另外:不能保證** row_number()over()**會產生所需的排序 - 使用EXPLICIT命令來保證排序。另見:http://stackoverflow.com/questions/1128737/unpivot-and-postgresql –

+0

我可以添加你的'支付組'號碼:) – flutter

+0

按要求添加空格。 – flutter

回答

1

版本空白(空文本)unnest功能,可以爲你做這個。 如果你想空的文本,那麼你可以在空文本列如果你想擁有使用此

SELECT ROW_NUMBER() OVER (ORDER BY paymentid) AS "group", 
unnest(array[1, 2, 3]) AS "line item", 
unnest(array[paymentid, '', '']) AS "paymentid", 
unnest(array[customercode, '', '']) AS "customercode", 
unnest(array['PREVIOUS BALANCE', 'PAYMENT AMOUNT', 'REMAINING BALANCE']) AS "type", 
unnest(array[previousbalance, paymentamount, remainingbalance]) AS "amount" 
FROM payment_info 
ORDER BY 1, 2 ; 

爲了得到這個

group | line item | paymentid | customercode |  type  | amount 
-------+-----------+-----------+--------------+-------------------+-------- 
    1 |   1 | PID0001 | CUST024  | PREVIOUS BALANCE | 10000 
    1 |   2 |   |    | PAYMENT AMOUNT | 2500 
    1 |   3 |   |    | REMAINING BALANCE | 7500 
    2 |   1 | PID0002 | CUST031  | PREVIOUS BALANCE | 8500 
    2 |   2 |   |    | PAYMENT AMOUNT | 3500 
    2 |   3 |   |    | REMAINING BALANCE | 5000 
    3 |   1 | PID0003 | CUST005  | PREVIOUS BALANCE | 12000 
    3 |   2 |   |    | PAYMENT AMOUNT | 1500 
    3 |   3 |   |    | REMAINING BALANCE | 10500 

,例如點或其他文本,或箭頭,您可以使用unnest輕鬆完成此操作。

您可以分別控制4個空文本值。

SELECT ROW_NUMBER() OVER (ORDER BY paymentid) AS "group", 
unnest(array[1, 2, 3]) AS "line item", 
unnest(array[paymentid, '  a', '  c']) AS "paymentid", 
unnest(array[customercode, '  b', '  d']) AS "customercode", 
unnest(array['PREVIOUS BALANCE', 'PAYMENT AMOUNT', 'REMAINING BALANCE']) AS "type", 
unnest(array[previousbalance, paymentamount, remainingbalance]) AS "amount" 
FROM payment_info 
ORDER BY 1, 2 ; 

產生

group | line item | paymentid | customercode |  type  | amount 
-------+-----------+-----------+--------------+-------------------+-------- 
    1 |   1 | PID0001 | CUST024  | PREVIOUS BALANCE | 10000 
    1 |   2 |  a |  b  | PAYMENT AMOUNT | 2500 
    1 |   3 |  c |  d  | REMAINING BALANCE | 7500 
    2 |   1 | PID0002 | CUST031  | PREVIOUS BALANCE | 8500 
    2 |   2 |  a |  b  | PAYMENT AMOUNT | 3500 
    2 |   3 |  c |  d  | REMAINING BALANCE | 5000 
    3 |   1 | PID0003 | CUST005  | PREVIOUS BALANCE | 12000 
    3 |   2 |  a |  b  | PAYMENT AMOUNT | 1500 
    3 |   3 |  c |  d  | REMAINING BALANCE | 10500 

這是一個非常靈活的解決方案,你知道的。

+0

感謝您的回答...如果我想要檢索30列以上的列表,最好使用這種查詢(unnest)? – john1717

+0

只需嘗試一下。它應該是非常有效的。 – flutter

1

這是沒有必要總是使用聯合查詢。例如,您可以使用3行和交叉連接。這具有在源表上僅有一次通過的優點。

drop table if exists Table1; 

CREATE TABLE Table1 
    ("paymentid" varchar(7), "customercode" varchar(7) 
    , "previousbalance" int, "paymentamount" int, "remainingbalance" int) 
; 

INSERT INTO Table1 
    ("paymentid", "customercode", "previousbalance", "paymentamount", "remainingbalance") 
VALUES 
    ('PID0001', 'CUST024', 10000, 2500, 7500), 
    ('PID0002', 'CUST031', 8500, 3500, 5000), 
    ('PID0003', 'CUST005', 12000, 1500, 10500) 
; 

select 
     paymentid 
    , customercode 
    , rn 
    , typeof 
    , case when rn = 1 then previousbalance 
      when rn = 2 then paymentamount 
      when rn = 3 then remainingbalance 
     end as Amount 
from Table1 
cross join (select 1 rn , 'previousbalance' typeof 
      union all 
      select 2 , 'paymentamount' 
      union all 
      select 3, 'remainingbalance' 
      ) rns 

這些數據/查詢產生這樣的結果:

+----+-----------+--------------+----+------------------+--------+ 
| | paymentid | customercode | rn |  typeof  | amount | 
+----+-----------+--------------+----+------------------+--------+ 
| 1 | PID0001 | CUST024  | 1 | previousbalance | 10000 | 
| 2 | PID0001 | CUST024  | 2 | paymentamount | 2500 | 
| 3 | PID0001 | CUST024  | 3 | remainingbalance | 7500 | 
| 4 | PID0002 | CUST031  | 1 | previousbalance | 8500 | 
| 5 | PID0002 | CUST031  | 2 | paymentamount | 3500 | 
| 6 | PID0002 | CUST031  | 3 | remainingbalance | 5000 | 
| 7 | PID0003 | CUST005  | 1 | previousbalance | 12000 | 
| 8 | PID0003 | CUST005  | 2 | paymentamount | 1500 | 
| 9 | PID0003 | CUST005  | 3 | remainingbalance | 10500 | 
+----+-----------+--------------+----+------------------+--------+ 

屆時請注意,SQL是不是「報告作家」所以在列毛坯「佈局」是不是一個好的適合SQL它想重複信息(就像你在結果中看到的那樣),以便你可以根據需要進行排序和過濾。

+0

注意到這一點...感謝您的答案..但是如何在這裏添加付款組列,每個付款ID都有一個自動編號 – john1717

+0

雖然可以使用unnest()函數來完成:)但是Postgres大象可以做很多魔術事情 – flutter

+0

僅僅因爲它可以完成這並不意味着它應該是。 –