Postgresql 将行数()与Update语句一起使用
希望只是一个简单的问题。我在UPDATE语句中使用row_number()时遇到了一些困难 假设我有一张书架桌:Postgresql 将行数()与Update语句一起使用,postgresql,Postgresql,希望只是一个简单的问题。我在UPDATE语句中使用row_number()时遇到了一些困难 假设我有一张书架桌: userid createddate bookid pagenumber 1 2021-18-01 charper 141 1 2021-17-01 mproust 136 1 2021-17-01 sking 134 1 2021-15-01 charper 128 1 2021-
userid createddate bookid pagenumber
1 2021-18-01 charper 141
1 2021-17-01 mproust 136
1 2021-17-01 sking 134
1 2021-15-01 charper 128
1 2021-10-01 jausten 122
2 2021-18-01 vwoolf 141
2 2021-17-01 vwoolf 136
2 2021-17-01 charper 134
我想(求和)相同的bookid页码,然后写到右边的列。我的预期结果必须是:
userid createddate bookid pagenumber countrow
1 2021-18-01 charper 141 269
1 2021-17-01 mproust 136 136
1 2021-17-01 sking 134 134
1 2021-15-01 charper 128
1 2021-11-01 jausten 122 122
2 2021-18-01 vwoolf 141 277
2 2021-17-01 vwoolf 136
2 2021-17-01 charper 134 134
我的选择语句
SELECT userid, bookid, pagenumber,
case when row_number() over (partition by userid, bookid order by bookid) = 1
then sum(pagenumber) over (partition by userid, bookid)
end as countrow
from usertable;
上面的sql查询非常适合在临时列上显示countrow。我想存储所有这些输出。所以我改成这样的陈述:
UPDATE bookshelf
SET countrow = countrow_new
FROM ( select userid, createddate, bookid, pagenumber,
case when row_number() over (partition by userid, bookid, order by bookid) = 1
then sum(pagenumber) over (partition by userid, bookid)
end as countrow_new
from bookshelf
)x
此查询似乎无法正常工作。它会用错误的值更新countrow中的所有单元格。我在谷歌上搜索,发现了一些有用的东西,比如和,但没什么。有没有人知道这里发生了什么,或者有没有人有过类似的问题?
如何解决此问题以获得预期结果?您正在尝试更新表中不存在的列(
countrow
),因此需要将此列添加到原始表并加入子查询:
/* add the column */
ALTER TABLE usertable ADD countrow INT;
/* do the update */
UPDATE usertable
SET countrow = countrow_new
FROM (
SELECT userid,
createddate,
bookid,
pagenumber,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY userid, bookid ORDER BY bookid) = 1
THEN SUM(pagenumber) OVER (PARTITION BY userid, bookid)
END AS countrow_new
FROM usertable
) x
JOIN usertable u
ON u.bookid = x.bookid AND u.createddate = x.createddate AND u.userid = x.userid;
以上假设{bookid,createddate,userid}
始终是唯一的
然而以这种方式将计算存储在表中是非常糟糕的设计和糟糕的做法-您必须在每次插入/更新/删除时使用触发器使列保持最新,这将对性能造成严重影响
更好的方法是采用原始查询并为其创建一个视图,然后可以将其用作表:
创建视图:
CREATE VIEW vwMyView
AS
SELECT userid,
bookid,
pagenumber,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY userid, bookid ORDER BY bookid) = 1
THEN SUM(pagenumber) OVER (PARTITION BY userid, bookid)
END AS countrow
FROM usertable;
SELECT * FROM vwMyView;
从视图中选择:
CREATE VIEW vwMyView
AS
SELECT userid,
bookid,
pagenumber,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY userid, bookid ORDER BY bookid) = 1
THEN SUM(pagenumber) OVER (PARTITION BY userid, bookid)
END AS countrow
FROM usertable;
SELECT * FROM vwMyView;
尚未测试此功能,但我认为您需要进行更新连接。我认为您可能需要额外的过滤器-RN-来只更新最新的bookid记录
WITH latestreadtotal AS
(
SELECT userid,
createddate,
bookid,
pagenumber,
row_number() OVER (partition BY userid, bookid order by bookid) AS rn,
CASE
WHEN row_number() OVER (partition BY userid, bookid, ORDER BY bookid) = 1 THEN sum(pagenumber) OVER (partition BY userid, bookid)
END AS countrow_new
FROM bookshelf )
UPDATE bsf
FROM bookshelf bsf
JOIN latestreadtotal lrt
ON bsf.userid = lrt.userid
AND bsf.createddate = lrt.createddate
AND bsf.bookid = lrt.bookid
AND bsf.pagenumber = lrt.pagenumber
AND lrt.rn = 1
我想您只需要将
更新
更改为x
:
UPDATE x
SET countrow = countrow_new
FROM (select userid, createddate, bookid, pagenumber,
(case when row_number() over (partition by userid, bookid, order by bookid) = 1
then sum(pagenumber) over (partition by userid, bookid)
end )as countrow_new
from bookshelf
) x;
您的代码引用子查询中的书架
。但是,结果称为x
。这可能意味着更新
中的书架
将作为单独的参考。我必须承认,SQL Server在update
s中有关于解析表引用的神秘规则。我通常只使用CTE进行这样的单表转换:
WITH toupdate AS (
select userid, createddate, bookid, pagenumber,
(case when row_number() over (partition by userid, bookid, order by bookid) = 1
then sum(pagenumber) over (partition by userid, bookid)
end )as countrow_new
from bookshelf
)
UPDATE toupdate
SET countrow = countrow_new;
根据您问题中的引用,我添加了SQL Server标记。请使用您正在使用的数据库标记问题。SQL Server或Postgres?当涉及到带有FROM子句的更新时,它们是非常不同的。