使用内连接进行查询的方法,用于更新 X 跳过锁定、排序和限制

Posted

技术标签:

【中文标题】使用内连接进行查询的方法,用于更新 X 跳过锁定、排序和限制【英文标题】:Way to make query with inner join, for update of X skip locked, ordering and limit 【发布时间】:2019-07-07 20:13:39 【问题描述】:

我需要获取表X的N条记录,但我需要使用INNER JOIN过滤这些记录,并事先对连接的记录进行相应的排序。

我尝试做的示例(可能不是 100% 准确,因为我使用的是 SQLAlchemy):

SELECT X.id
FROM X
   INNER JOIN Y ON X.id = Y.other_id
WHERE Y.condition_one
ORDER BY Y.condition_two
LIMIT 10
FOR UPDATE OF X SKIP LOCKED;

当我这样做时,我得到少于 10 个不同的 ids(可能是因为连接的行是有限的),但是,我无法执行 DISTINCT FOR UPDATE。我想我不能使用子查询,因为FOR UPDATE

我该怎么办?

【问题讨论】:

【参考方案1】:

您可以使用横向连接:

SELECT X.id
FROM X
   CROSS JOIN LATERAL (
      SELECT Y.condition_two
      FROM Y
      WHERE X.id = Y.other_id
        AND Y.condition_one
      ORDER BY Y.condition_two
      LIMIT 1) AS first_y
ORDER BY first_y.condition_two
LIMIT 10
FOR UPDATE OF X SKIP LOCKED;

或者(更简单)使用带有DISTINCT 的子选择:

SELECT X.id
FROM X
   JOIN (SELECT DISTINCT X.id
         FROM X
            INNER JOIN Y ON X.id = Y.other_id
         WHERE Y.condition_one
         ORDER BY Y.condition_two
         LIMIT 10) AS sub_x
      ON X.id = sub_x.id
FOR UPDATE OF X SKIP LOCKED;

【讨论】:

谢谢@Laurenz,你的回答让我豁然开朗,让我自己解决:-)【参考方案2】:

我无法同时使用 DISTINCT 和 ORDER BY。

理论上 LATERAL 连接应该可行,但在实现时,我发现了另一种方法:

SELECT X.id
FROM X
   JOIN (SELECT X.id, MIN(Y.condition_two) AS ordering
         FROM X
            INNER JOIN Y ON X.id = Y.other_id
         WHERE Y.condition_one) AS sub_x
      ON X.id = sub_x.id
ORDER BY ASC(sub_x.ordering)
LIMIT 10
FOR UPDATE OF X SKIP LOCKED;

如果我想使用 DESC 订购,我必须将 MIN 更改为 MAX。

【讨论】:

以上是关于使用内连接进行查询的方法,用于更新 X 跳过锁定、排序和限制的主要内容,如果未能解决你的问题,请参考以下文章

选择从 JPA 级别锁定的更新跳过

SELECT FOR UPDATE 用于锁定查询

选择以行限制锁定更新跳过

FMDatabase 锁定,类内使用的最佳实践

为啥在选择的更新跳过锁定时,若有的几个会话可以看到行?

如何执行选择查询,而不锁定更新查询