在 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 中提取 id
或 name
。
【参考方案1】:
这是我能用您的 JSON 输入和示例输出做的最好的事情。
请注意,您的文档具有唯一的 "id"
和 "name"
(在您的示例中为 "1"
和 "test"
)。然后它有一个名为"productSpecificationRelationship"
的数组。这个数组的每个元素都是一个拥有自己的"id"
的对象——在查询中,我用列名PSR_ID
(PSR 表示产品规范关系)显示了这个id。此外,这个第一级数组中的每个对象都包含一个子数组(第二级),其中的对象具有"name"
(又是“名称”!)和"value"
键。 (这看起来很像实体属性值模型 - 非常糟糕的做法。)在查询的中间步骤(在旋转之前),我将它们称为 RC_NAME
和 RC_VALUE
(关系特征的 RC)。
在您的示例输出中,ID
和 NAME
列中有多个值。我不明白这是怎么可能的;也许来自解压多个文件?您与我们共享的 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 在多个列上旋转多个组的最有效方法?