是否有一种优化此查询的方法,该方法涉及将json拆包?

时间:2019-08-23 16:29:09

标签: sql postgresql

我编写了一个查询,该查询几乎返回了我需要的数据,但我不能完全解决。我对SQL有点生疏,但基本上我正试图通过以下方式获得行结构:

  • 用户名,颜色,codeId,actionDate

符合条件:

  • 行匹配email
  • 显示了actionDate动作的最新enabled(有很多,所以我想最新)。如果没有actionDate可用于enabled的操作,则显示null

    actions看起来像这样:

    ID      email               action          jsonData                                                                actionDate
    1       bob@example.com     enabled         {"Color": "Blue", "Username": "user.a@example.com", "Delta": null}      2019-01-05
    4       bob@example.com     enabledForce    {"Color": "Blue", "CodeId": "004", "Username": "user.a@example.com"}    2019-01-20
    5       bob@example.com     enabled         {"Color": "Blue", "Username": "user.b@example.com", "Delta": null}      2019-01-05
    6       bob@example.com     enabledForce    {"Color": "Blue", "CodeId": "009", "Username": "user.b@example.com"}    2019-01-14
    23      bob@example.com     enabledForce    {"Color": "Red", "Username": "user"}                                    2019-01-06
    56      bob@example.com     enabled         {"Color": "Blue", "Username": "user.b@example.com", "Delta": null}      2019-01-05
    443     bob@example.com     enabled         {"Color": "Blue", "Username": "user.a@example.com", "Delta": null}      2019-01-05
    2356    bob@example.com     enabledForce    {"Color": "Blue", "CodeId": "004", "Username": "user.a@example.com"}    2019-01-23
    4353    bob@example.com     enabled         {"Color": "Blue", "Username": "user.a.b@example.com", "Delta": null}    2019-01-19
    4535    bob@example.com     enabledForce    {"Color": "Blue", "CodeId": "005", "Username": "user.a.b@example.com"}  2019-01-23
    5643    bob@example.com     enabled         {"Color": "Blue", "Username": "anotheruser@google.com", "Delta": null}  2019-08-03

这是我尝试过的查询:

select username,
       color,
       codeId,
       min(DateEnabled),
from (
      SELECT distinct 
             jsonData ->> 'username' AS username,
             jsonData ->> 'color'    AS color,
             jsonData ->> 'codeId'    AS codeId,
             min(CASE
                 WHEN action_name = 'enabled'
                     THEN actionDate
                     ELSE NULL
                 END) AS DateEnabled,
             jsonData
       FROM actions
           where jsonData ->> 'Username' is not null
           and email = 'bob@example.com'
           and (action_name = 'enabled' or
                action_name = 'enabledForce')
           group by username, actionDate, jsonData 
   ) as inquery
   group by username, orgcolorype, codeId

这将返回如下所示的数据:

username               color   codeId   DateEnabled
-------------------------------------------------------------------
user                    Red             2019-01-06
user.a@example.com      Blue    004     2019-01-05
user.a@example.com      Blue        
user.a.b@example.com    Blue    005     2019-01-19
user.a.b@example.com    Blue        
user.b@example.com      Blue    009     2019-01-05
user.b@example.com      Blue        
anotheruser@google.com  Blue        

上面是我想要的,但是请使用具有日期(如果可用)的用户名,否则默认为null:

user                    Red             2019-01-06
user.a@example.com      Blue    004     2019-01-05
user.a.b@example.com    Blue    005     2019-01-19
user.b@example.com      Blue    009     2019-01-05  
anotheruser@google.com  Blue

1 个答案:

答案 0 :(得分:0)

更改此

action_name = 'enabled' OR action_name = 'enabledForce'

action_name IN ('enabled', 'enabledForce')

并创建此索引:

CREATE INDEX ON actions (email, action_name)
   WHERE jsonData ->> 'Username' IS NOT NULL;

要始终获取具有最新dateenabled的行,请使用如下结构:

select DISTINCT ON(username)
       username,
       color,
       codeId,
       DateEnabled
/* your FROM */
ORDER BY dateenabled DESC NULLS LAST,
         color,
         codeid;