【问题标题】:Way to make query with inner join, for update of X skip locked, ordering and limit使用内连接进行查询的方法,用于更新 X 跳过锁定、排序和限制
【发布时间】: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

我该怎么办?

【问题讨论】:

    标签: postgresql distinct select-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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      相关资源
      最近更新 更多