当前位置: 首页 > 知识库问答 >
问题:

Postgresql选择,直到达到一定的总量并锁定

萧伟兆
2023-03-14

我有一个用户批次表。我只想选择,直到我的总金额达到一定金额。

id  | user_id | balance | batch_id 
----|---------|-------- |--------
 1  | 1       |   2     | 1
 2  | 2       |   15    | 2
 3  | 1       |   8     | 3
 4  | 1       |   5     | 4 
 5  | 2       |   7     | 5
 6  | 1       |   1     | 6
 7  | 2       |   5     | 7

考虑以下查询:

SELECT * FROM tb_batch_user WHERE user_id = 1 ORDER BY batch_id asc

查询结果为:

    id  | user_id | balance | batch_id 
    ----|---------|-------- |--------
     1  | 1       |   2     | 1
     3  | 1       |   8     | 3
     4  | 1       |   5     | 4 
     6  | 1       |   1     | 6

我想在表格上做一个选择,直到余额总数为6。然后只返回id 1,2:

    id  | user_id | balance | batch_id 
    ----|---------|-------- |--------
     1  | 1       |   2     | 1
     3  | 1       |   8     | 3

余额总计为1的另一个示例。那么应该只返回ids 1:

    id  | user_id | balance | batch_id 
    ----|---------|-------- |--------
     1  | 1       |   2     | 1

余额合计为11的示例。应该只返回ids,3,4:

    id  | user_id | balance | batch_id 
    ----|---------|-------- |--------
     1  | 1       |   2     | 1
     3  | 1       |   8     | 3
     4  | 1       |   5     | 4

所以,在那之后,我需要用FORUPDATE ex锁定这些行:

     SELECT * FROM tb_batch_user WHERE user_id = 1 ORDER BY batch_id asc FOR UPDATE

我尝试了窗口功能,但它不允许锁定(更新)。感谢任何帮助。

共有3个答案

艾焕
2023-03-14

下面是一种使用窗口函数的方法:

select id, balance, user_id, batch_id
from (
    select t.*, 
        sum(balance) over(partition by user_id order by id) sum_balance
    from mytable t
    where user_id = 1
) t
where sum_balance - balance < 6

您需要一个累积余额,直到第一个余额等于或超过阈值。为此,您可以只使用一个窗口< code>sum()。

您可以将不等式条件更改为所需的阈值。您还可以更改(或删除)子查询中对user_id的筛选。

我们可以使用子查询轻松实现相同的逻辑,这将支持进行更新

select *
from mytable t
where user_id = 1 and (
    select coalesce(sum(balance), 0)
    from mytable t1
    where t1.user_id = t.user_id and t1.id < t.id
) < 6
for update

DB Fiddle上的演示:

id | balance | user_id
-: | ------: | ------:
 1 |       2 |       1
 3 |       8 |       1
赵志
2023-03-14

你在找这个吗?

with w0 as (
  select id, user_id, balance, batch_id,
     coalesce(lag(running_balance) over (partition by user_id order by batch_id asc), 0) running_balance 
  from (
      SELECT t.* ,
        sum(balance) over (partition by user_id order by batch_id asc) running_balance
      FROM tb_batch_user t 
      --where t.user_id = 1
  ) x 
)
select * from w0
where running_balance < 6

PS:您可以添加user_id作为where子句。请参见注释

为了锁定,

select * from tb_batch_user tb
where tb.id in (select w0.id from w0 where running_balance < 6)
for update 
孟成化
2023-03-14

我能够选择。。。对于使用窗口函数进行更新:

with inparms as (
  select 1 as user_id, 6 as target
), rtotal as (
  select t.id, i.target,
         sum(t.balance) over (partition by t.user_id
                                  order by t.id
                              rows between unbounded preceding
                                       and 1 preceding) as runbalance
    from tb_batch_user t
         join inparms i 
           on i.user_id = t.user_id
)
select t.*
  from rtotal r
       join tb_batch_user t
         on t.id = r.id
 where coalesce(r.runbalance, 0) < r.target
for update of t;

在这里拉小提琴

 类似资料:
  • 问题内容: 我正在使用SQL Server 2012,并且正在尝试执行以下操作: 因此,换句话说,我想从表中选择具有指定的截止日期和日期的随机行,并在里程总和等于或大于该数字时停止:3250 问题答案: 由于您使用的是SQL Server 2012,因此这是一种无需循环的简单方法。 SQLfiddle演示-多次单击“运行SQL”以查看随机结果。

  • 问题内容: 我有一个可以支持一定数量的并发操作的应用程序。这由postgres中的“插槽”表表示。当节点联机时,它们会在表中插入许多行,每个插槽一个。当作业声明插槽时,它们会更新表中声明其中一个插槽的行,并在完成时再次释放它。 插槽表如下所示: 在任何时候,它都有一些固定的行数,每行可以或可以不填写job_name。 当新作业要启动时,它将运行以下查询以获取应在其上运行的节点的名称: (从游标中读

  • 问题内容: 我需要一个SQL查询来从消息队列中选择行,直到SUM(users_count)最多达到1000。 但是 ,如果仅返回一行并且该行的users_count大于1000,就没有问题。 我需要类似的内容:(我添加了自己的关键字) 这是我的表结构: messages_queue -msg_id -msg_body-users_count (消息接收方的数量) -时间(插入时间) 问题答案: 该

  • 问题内容: 我已经在SF中看到了这个问题,但是我是菜鸟,只是无法让我的头脑变得模糊。因此,如果您想重复,请原谅我。 我的样品表 我需要获取“ UNTIL”行,对于特定的供应商ID,“ QTY”的累计总数按降序等于或大于5。 在此示例中,对于供应商1,它将是ID为5和2的行。 问题答案: 这个怎么样?使用两个变量。 SQLFIDDLE演示 询问:

  • 问题内容: 如何查询和显示记录直到达到一定数量? 假设您要选择学生,直到学生的总金额达到1000? 加成 如果我想停在500,我会得到记录1和2(190 + 290)。如果我想停在1000,我会得到记录1直到4。 问题答案: SQL表没有“内部”顺序,因此您必须指定一些ORDER BY子句以赋予“直到”短语任何含义。鉴于此,可以使用来自学生ORDER BY xxx LIMIT N的SELECT S

  • 我有一个表和几个线程(系统),它们从表中读取特定列并更新它。因此,我的问题如下: 我想确保在任何时候只有一个线程可以选择和更新该列。最好的解决方案是什么? PS:据我所知,在SQL Server中使用事务会锁定事务中的所有资源,但我对PostgreSQL一无所知。 非常感谢。