2017-05-08 30 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

仅仅因为它可以完成这并不意味着它应该是。 –