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

时间:2019-02-13 21:21:22

标签: postgresql distinct select-for-update

我需要获取表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;

执行此操作时,我得到的独立id少于10个(可能是因为连接的行受到限制),但是,我无法使用以下命令执行DISTINCT FOR UPDATE。由于FOR UPDATE,我想我不能使用子查询。

我该怎么办?

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

我无法同时使用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。