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个组合动作。
我只需要有关如何获得函数结构的帮助 - 循环?如果?如何保存行?无需编写组合代码。
为了简化,假设只有两行selected
为TRUE
。
注意:func1
应该将新状态保存到A
。
答案 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
;