如何在表postgresql中组合两行?

时间:2015-08-18 05:51:52

标签: sql postgresql

Normaly我不会问这个问题,但是我有一些独特的情况,我在如何做到这一点时遇到了麻烦。

我有一张表A,如下所示:

uniqueid , itemid, quantity, selected
1            2455     10        TRUE
2            7458     50        FALSE
3            58494    20.6      FALSE
4            2455     20        TRUE

我需要编写一个合并函数,它接受同一部分的TRUE行并将它们组合成一行(使用更新的quantity)。

意思是我想得到:

uniqueid , itemid, quantity, selected
1            2455     30        FASLE
2            7458     50        FALSE
3            58494    20.6      FALSE/TRUE (doesn't matter)

OR:

uniqueid , itemid, quantity, selected
2            7458     50        FALSE
3            58494    20.6      FALSE
4            2455     30        FALSE/TRUE (doesn't matter)

我的功能没有获得任何参数...我需要一些方法,我可以识别并使用所选择的行。 首先我想到了:

CREATE OR REPLACE FUNCTION func1()
  RETURNS void AS 
$BODY$
declare 
    ROW RECORD
begin
for ROW in select * from A where selected
    LOOP
        do combine code     
    end loop;
end;                
$BODY$
  LANGUAGE plpgsql VOLATILE

然而,这个代码不会起作用,因为在每个组合后两行变为一个。在上面的例子中,循环将生成两个迭代,但我只需要1次迭代..只需要1个组合动作。

我只需要有关如何获得函数结构的帮助 - 循环?如果?如何保存行?无需编写组合代码。

为了简化,假设只有两行selectedTRUE

注意func1应该新状态保存到A

3 个答案:

答案 0 :(得分:2)

一个简单的解决方案是在联合中执行此操作 - 在这种情况下,使用selected = false的行数也无关紧要:

select min(uniqueid) as uniqueid,
       itemid, 
       sum(quantity) as quantity, 
       false as selected
from a 
where selected
group by itemid
union all
select uniqueid,
       itemid,
       quantity,
       selected
from a
where not selected
order by 1;

编辑后,澄清该表应该被修改。

您可以使用修改CTE的数据执行此操作。在第一步中,更新数量的总和,在第二步中删除不再需要的行:

with updated as (
  -- this updates the lowest uniqueid with the total sum
  -- of all rows. If you want to keep/update the highest
  -- uniqueid change the min() to max()
  update a 
    set quantity = t.total_sum,
        selected = false
  from (
    select min(uniqueid) as uniqueid,
           itemid, 
           sum(quantity) as total_sum
    from a 
    where selected
    group by itemid
  ) t
  where t.uniqueid = a.uniqueid 
  returning a.uniqueid
)
-- this now deletes the rows that are still marked
-- as "selected" and where not updated
delete from a
where selected
  and uniqueid not in (select uniqueid from updated);

这假设uniqueid列确实是唯一的(例如主键或定义了唯一索引/约束)。必须更改selected列的值才能使其生效。因此,如果在此过程中将selected设置为false,则 无关紧要。

答案 1 :(得分:0)

您可能想尝试使用UNION或许

SELECT u.* 
FROM (
  SELECT MIN(t.uniqueid) AS uniqueid,
    t.itemid,
    SUM(t.quantity) AS quantity,
    FALSE AS selected
  FROM table_name t
    WHERE t.selected = TRUE
    GROUP BY t.itemid
  UNION
  SELECT t.uniqueid,
    t.itemid,
    t.quantity,
    t.selected
  FROM table_name t
    WHERE t.selected = FALSE) u
  ORDER BY u.uniqueid ASC

答案 2 :(得分:0)

你没有告诉任何关于uniqueid嬗变和选定列的内容,但我认为你想要像这样的smth:

select distinct uniqueid,itemid,quantity,selected
from (
select 
 case when selected then max(uniqueid) over (partition by selected) else uniqueid end uniqueid 
 , itemid
 , case when selected then sum(quantity) over (partition by selected) else quantity end quantity 
 , false  selected
from t113
) init
order by 1
;