当有多个同名时更新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 1
和 3
中的 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
的行中设置 shares
到 0
的列,并在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.
我会尽力解释我的问题。
我正在研究 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 1
和 3
中的 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
的行中设置 shares
到 0
的列,并在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.