当有多个同名时更新sqlite数据库中的值

Update values in sqlite database when there are multiple with the same name

我会尽力解释我的问题。

我正在研究 cs50 C Finanace 目前正在实现一个名为 sell 的功能。此函数的目的是将特定用户的现金价值更新到数据库中并更新他的投资组合。

我正在努力更新投资组合数据库。

为了更好地说明,这是数据库查询:

CREATE TABLE portfolio(id INTEGER, username TEXT NOT NULL, symbol TEXT NOT NULL, shares INTEGER, PRIMARY KEY(id));

假设我有这些值:

id | username | symbol | shares

1 | eminem | AAPL | 20

2 | eminem | NFLX | 5

3 | eminem | AAPL | 5

并且用户卖出了他的一些股票。我必须更新 shares。 如果是 NFLX 符号就很容易了。像下面这样的简单查询就足够了

db.execute("UPDATE portfolio SET shares=shares - ? WHERE username=? AND symbol=?", int(shares), username, quote["symbol"])

但是,如果我想更新 AAPL 共享,这就是问题出现的地方。如果我执行上面的查询,假设用户卖掉了他的 5 股,上面的查询会将 ids 13 中的 AAPL 股更改为 20,使总股数AAPL 到 40 而不是 20。

我应该考虑哪种方法?在将它们插入 portfolio table 之前,我是否应该根据代码对股票进行分组?如果是这样,如何?或者有可以解决我的问题的查询吗?

如果您的 SQLite 版本是 3.33.0+,则使用 UPDATE...FROM 语法,如下所示:

UPDATE portfolio AS p
SET shares = (p.id = t.id) * t.shares_left
FROM (
  SELECT MIN(id) id, username, symbol, shares_left 
  FROM (
    SELECT *, SUM(shares) OVER (ORDER BY id) - ? shares_left -- change ? to the number of stocks the user sold 
    FROM portfolio
    WHERE username = ? AND symbol = ?
  ) 
  WHERE shares_left >= 0
) AS t
WHERE p.username = t.username AND p.symbol = t.symbol AND p.id <= t.id;

window 函数 SUM() returns 股票的增量总和,直到达到已售出的股票数量。
UPDATE 语句将在所有 id 小于超过已售股票的第一个 id 的行中设置 shares0 的列,并在id 的行等于第一个 id 超过已售出股票的增量总和与已售出股票数量之间的差值。

查看简化版 demo.

对于以前的版本,您可以使用这个:

WITH 
  cte AS (
    SELECT MIN(id) id, username, symbol, shares_left 
    FROM (
      SELECT *, SUM(shares) OVER (ORDER BY id) - ? shares_left -- change ? to the number of stocks the user sold  
      FROM portfolio
      WHERE username = ? AND symbol = ?
    ) 
    WHERE shares_left >= 0
  )
UPDATE portfolio
SET shares = (id = (SELECT id FROM cte)) * (SELECT shares_left FROM cte) 
WHERE (username, symbol) = (SELECT username, symbol FROM cte) AND id <= (SELECT id FROM cte)

查看简化版 demo.