首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查询优化

查询优化
EN

Database Administration用户
提问于 2020-08-20 08:17:03
回答 1查看 79关注 0票数 3

我想从两个表(orders, actions)中优化两个查询,其关系为1到多

现在我从订单中做出一个选择:

代码语言:javascript
复制
SELECT "id"
FROM   "orders"
WHERE "orders"."status" = 'new' 

然后,对于我选择的每一个订单:

代码语言:javascript
复制
SELECT *
FROM   "actions" AS "actions" 
WHERE  "actions"."status" IN ( 'new', 'processing' ) 
       AND "actions"."order_id" = ${orderId} 
ORDER  BY CASE 
            WHEN ( "status" = 'processing' ) THEN 0 
            WHEN( "status" = 'new' ) THEN 1 
            ELSE 2 
          END ASC, 
          CASE 
            WHEN ( "direction" = 'out' ) THEN 0 
            WHEN( "direction" = 'in' ) THEN 1 
            ELSE 2 
          END ASC, 
          "actions"."id" ASC 
LIMIT  1; 

在代码中,我检查action.due_date <= now是否做了什么事情。

我试过:

代码语言:javascript
复制
SELECT o.status, ac.* FROM (
    SELECT *
    FROM   "actions" AS "actions" 
    WHERE  "actions"."status" IN ( 'new', 'processing' )
    ORDER  BY   CASE 
            WHEN ( "status" = 'processing' ) THEN 0 
            WHEN( "status" = 'new' ) THEN 1 
            ELSE 2 
          END ASC, 
          CASE 
            WHEN ( "direction" = 'out' ) THEN 0 
            WHEN( "direction" = 'in' ) THEN 1 
            ELSE 2 
          END ASC, 
          "actions"."id" ASC 
    LIMIT  1) AS ac
INNER JOIN orders o on o.id = ac.order_id
where ac.due_date <= ${now}
AND o.status = 'new'

以及:

代码语言:javascript
复制
SELECT * FROM orders as o
INNER JOIN (
    SELECT *
    FROM   "actions" AS "actions" 
    WHERE  "actions"."status" IN ( 'new', 'processing' )
    ORDER  BY   CASE 
            WHEN ( "status" = 'processing' ) THEN 0 
            WHEN( "status" = 'new' ) THEN 1 
            ELSE 2 
          END ASC, 
          CASE 
            WHEN ( "direction" = 'out' ) THEN 0 
            WHEN( "direction" = 'in' ) THEN 1 
            ELSE 2 
          END ASC, 
          "actions"."id" ASC 
    LIMIT  1) a on a.order_id = o.id AND a.due_date <= ${now}
where o.status = 'new' 

数据和所需答复的实例:

代码语言:javascript
复制
Order table
id  status
1   new
2   new

Actions table:
id  order_id     status      direction    due_date
1     1          success     out          now-1
2     1          processing  in           now+1
3     1          new         out          now-1
4     2          success     out          now-1
5     2          new         in           now-1
6     2          closed      out          now-1

响应:

代码语言:javascript
复制
id  order_id     status      direction    due_date
5   2            new         in           now-1

Order id 1不存在,因为操作id 2、due_date > now和其他操作需要等待,直到这个操作被处理。

Ps。操作表较小,我认为应该开始从选择操作中选择,以使选择更快/更优。

提前感谢

<#>编辑

添加木琴

EN

回答 1

Database Administration用户

发布于 2020-08-20 11:37:56

这里有一个使用横向的想法:

代码语言:javascript
复制
SELECT o.status, ac.* 
FROM orders o 
CROSS JOIN LATERAL (
    SELECT *
    FROM   "actions" AS "actions" 
    WHERE  "actions"."status" IN ( 'new', 'processing' )
      AND  due_date <= ${now}
      AND  o.id = order_id    -- push join predicate inside sub-select
    ORDER  BY   CASE 
            WHEN ( "status" = 'processing' ) THEN 0 
            WHEN( "status" = 'new' ) THEN 1 
            ELSE 2 
          END ASC, 
          CASE 
            WHEN ( "direction" = 'out' ) THEN 0 
            WHEN( "direction" = 'in' ) THEN 1 
            ELSE 2 
          END ASC, 
          "actions"."id" ASC 
    LIMIT  1
) AS ac
WHERE o.status = 'new'

与我重新安排的查询相比,语义略有不同。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/274046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档