在 Oracle DBMS 中的多个列上使用过滤条件连接表

Posted

技术标签:

【中文标题】在 Oracle DBMS 中的多个列上使用过滤条件连接表【英文标题】:Joining tables with filter condition on multiple columns in Oracle DBMS 【发布时间】:2021-02-20 20:58:54 【问题描述】:

“描述”:“测试”, “id”:“1”, “名称”:“测试”,

“产品”:[ “id”:“1”, “名称”:“名称”, “关于”: [ “名称”:“名称1”, “价值”:“1” , “名称”:“名称2”, “价值”:“1” , “名称”:“名称3”, “价值”:“0” , “名称”:“名称 4”, “价值”:“0” ] ]

【问题讨论】:

您发布的查询对您有用吗?它不适合我。您在SELECT 子句中选择什么“id”和“name”?您没有从查询中的 JSON 中提取 idname 【参考方案1】:

这是我能用您的 JSON 输入和示例输出做的最好的事情。

请注意,您的文档具有唯一的 "id""name"(在您的示例中为 "1""test")。然后它有一个名为"productSpecificationRelationship" 的数组。这个数组的每个元素都是一个拥有自己的"id" 的对象——在查询中,我用列名PSR_ID(PSR 表示产品规范关系)显示了这个id。此外,这个第一级数组中的每个对象都包含一个子数组(第二级),其中的对象具有"name"(又是“名称”!)和"value" 键。 (这看起来很像实体属性值模型 - 非常糟糕的做法。)在查询的中间步骤(在旋转之前),我将它们称为 RC_NAMERC_VALUE(关系特征的 RC)。

在您的示例输出中,IDNAME 列中有多个值。我不明白这是怎么可能的;也许来自解压多个文件?您与我们共享的 JSON 文档具有 "id""name" 作为***属性。

在输出中,我理解(或者更确切地说,假设,因为我对您的问题不太了解)您应该还包括 PSR_ID - 您的文件中只有一个文档,值为"10499",但原则上可能不止一个,并且每个这样的id输出一行。

另外,我假设“名称”值仅限于您提到的四个(或者,如果可以有更多,您只对输出中的这四个感兴趣)。

说了这么多,这里是查询。请注意,为简单起见,我将表称为 ES。此外,您会看到我必须访问 nested path 两次(因为您的文档包含一个数组数组,我想从外部数组中取出 PSR_ID 并从嵌套数组中取出标记)。

表格设置

create table es (payloadentityspecification clob 
                 check (payloadentityspecification is json) );                  
insert into es (payloadentityspecification) values (
'
  "description": "test",
  "id": "1",
  "name": "test",
  "productSpecificationRelationship": [
    
      "id": "10499",
      "relationshipType": "channelRelation",
      "relationshipCharacteristic": [
        
          "name": "out_of_home",
          "value": "1"
        ,
        
          "name": "out_of_home_ios",
          "value": "1" 
        ,
        
          "name": "out_of_home_android",
          "value": "0"
        ,
        
          "name": "out_of_home_web",
          "value": "0"
        
      ]
     
  ]
');
commit;

查询

with
  prep (id, name, psr_id, rc_name, rc_value) as (
    select id, name, psr_id, rc_name, rc_value
    from   es,
           json_table(payloadentityspecification, '$'
                      columns (
                                id   varchar2(10) path '$.id',
                                name varchar2(40) path '$.name',
                          nested path '$.productSpecificationRelationship[*]'
                          columns (
                                    psr_id varchar2(10) path '$.id',
                              nested path '$.relationshipCharacteristic[*]'
                              columns (
                                        rc_name  varchar2(50) path '$.name',
                                        rc_value varchar2(50) path '$.value'
                              )         
                          )
                      )
           )
  )
select id, name, psr_id, ooh, ooh_android, ooh_ios, ooh_web
from   prep
pivot ( min(case rc_value when '1' then 'TRUE' 
                          when '0' then 'FALSE' else 'UNDEFINED' end)
        for rc_name in ( 'out_of_home'         as ooh,
                         'out_of_home_android' as ooh_android,
                         'out_of_home_ios'     as ooh_ios,
                         'out_of_home_web'     as ooh_web
                       )
      )
;

输出

ID NAME PSR_ID OOH         OOH_ANDROID OOH_IOS     OOH_WEB  
-- ---- ------ ----------- ----------- ----------- -----------
1  test 10499  TRUE        FALSE       TRUE        FALSE  

【讨论】:

感谢您的宝贵时间,请求的结果和正确的重新思考时间不到一秒钟,结果非常好,我非常感谢【参考方案2】:

条件聚合可用于在使用JSON_TABLE()JSON_VALUE() 等函数提取值后对结果集进行透视

 SELECT JSON_VALUE(payloadentityspecification, '$.name') AS channel_map_name,
        MAX(CASE WHEN name = 'out_of_home' THEN 
                      DECODE(value,1,'TRUE',0,'FALSE','UNDEFINED')
                  END) AS ooh,
        MAX(CASE WHEN name = 'out_of_home_android' THEN 
                      DECODE(value,1,'TRUE',0,'FALSE','UNDEFINED')
                  END) AS ooh_android,
        MAX(CASE WHEN name = 'out_of_home_ios' THEN 
                      DECODE(value,1,'TRUE',0,'FALSE','UNDEFINED')
                  END) AS ooh_ios,
        MAX(CASE WHEN name = 'out_of_home_web' THEN 
                      DECODE(value,1,'TRUE',0,'FALSE','UNDEFINED')
                  END) AS ooh_web                  
   FROM EntitySpecification ES,
   JSON_TABLE (payloadentityspecification, '$.productSpecificationRelationship[*]'
                    COLUMNS (  NESTED PATH '$.relationshipCharacteristic[*]'
                    COLUMNS (                
                             description VARCHAR2(250) PATH '$.description',
                             name        VARCHAR2(250) PATH '$.name',
                             value       VARCHAR2(250) PATH '$.value'
                            )
   )) jt
  WHERE payloadentityspecification IS JSON
 GROUP BY JSON_VALUE(payloadentityspecification, '$.name')

Demo

【讨论】:

非常感谢您的时间,请求的结果是正确的,但是响应时间很慢12秒500条记录,非常感谢

以上是关于在 Oracle DBMS 中的多个列上使用过滤条件连接表的主要内容,如果未能解决你的问题,请参考以下文章

使用 Oracle SQL 在多个列上旋转多个组的最有效方法?

在 Oracle apex 中的列上设置自定义验证

使用 dbms_job 在包内执行 oracle 中的存储过程

T-SQL 根据另一表列过滤一列上的多个值

oracle存储过程如何输出信息

在 pyspark 中的特定列上应用过滤器描述