【问题标题】:Postgresql, Updating table row for each row in another tablePostgresql,为另一个表中的每一行更新表行
【发布时间】:2020-02-14 09:31:32
【问题描述】:

我正在学校里用 java/postgresql 做一个项目,在那里你可以购买不同音乐会的门票,但我被困在一个地方,我想编写一个代码,以便在音乐会被取消时退还所有款项.

我想从我的用户那里删除门票,并以他们购买门票的价格退还他们。

我的已售票表如下所示:

我的用户表如下所示,其中比塞塔是用户的货币:

我写了这个,但它只返回用户第一张票的比塞塔。

WITH tic AS (
SELECT userid, price, ticketamount
FROM piljetter_system.soldtickets tic
WHERE consertid = 2  // is example number
)
UPDATE piljetter_system.users usr SET pesetas = pesetas + (tic.price * tic.ticketamount)
FROM tic
WHERE usr.userid = tic.userid;

当我这样做时:

SELECT * FROM tic;

返回

在这里您可以看到 userid=5 两次购买了 consertid=2 的门票,一次他以 425 的价格购买了 5 张门票,另一次他以 200 的价格购买了同一个 consertid 的门票,3 张门票。 我上面的当前脚本仅将用户第一次购买的钱(5 * 425 比塞塔)退还给用户,我需要退还所有门票。

我也一直这样尝试,结果一样,只是更新了一行。:

UPDATE piljetter_system.users allusr
SET pesetas = (tic.price * tic.ticketamount) + allusr.pesetas
FROM piljetter_system.soldtickets tic , piljetter_system.users usr
WHERE tic.userid = allusr.userid
AND tic.consertid=2;

感谢您的帮助! :)

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    您不能在 UPDATE 语句中两次更新同一行,如 the documentation 所说:

    当使用FROM 时,您应该确保连接最多为要修改的每一行生成一个输出行。换句话说,目标行不应连接到来自其他表的多个行。如果是这样,那么只有一个连接行将用于更新目标行,但将使用哪一个是不容易预测的。

    所以你应该对每个用户的价格进行分组:

    WITH tic AS (
       SELECT userid,
              sum(price * ticketamount) AS total_price
       FROM piljetter_system.soldtickets tic
       WHERE consertid = 2
       GROUP BY userid
    )
    UPDATE piljetter_system.users usr
       SET pesetas = pesetas + tic.total_price
    FROM tic
    WHERE usr.userid = tic.userid;
    

    或者,使用子选择:

    UPDATE piljetter_system.users usr
       SET pesetas = pesetas + tic.total_price
    FROM (SELECT userid,
                 sum(price * ticketamount) AS total_price
          FROM piljetter_system.soldtickets tic
          WHERE consertid = 2
          GROUP BY userid) AS tic
    WHERE usr.userid = tic.userid;
    

    第二个变种在 v12 之前的 PostgreSQL 上可能更快。

    【讨论】:

    • 谢谢!没想到 sum() 他们在一起。
    • 我可能错了,但是总价和票数看起来像错误的解决方案,因为如果您尝试计算结果,您将得到错误的退款金额。 625 * 8 != 425 *5 + 200 * 3
    【解决方案2】:

    您可以使用 sum 函数预先计算您的退款价格,然后在更新中使用它:

    WITH tic AS (
      SELECT userid,  sum(price * ticketamount) as refund_price
      FROM piljetter_system.soldtickets tic
      WHERE consertid = 2
      GROUP BY userid
    )
    UPDATE piljetter_system.users usr SET pesetas = pesetas + tic.refund_price
    FROM tic
    WHERE usr.userid = tic.userid;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 2020-08-10
      • 2022-12-10
      • 2018-08-02
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多