oracle - clob 内的不同值
问题描述
我有一些 SQL 可以从多个地方拉回数据,然后将其显示在一行、两个单元格中。每个单元格中都有一个数据列表。如果我分解 SQL,最初数据会显示如下:
姓名 | 颜色类型 |
---|---|
橙子 | 金子 |
黄色 | 香蕉 [CHR(10)] 金 |
很抱歉这个奇怪的表,但基本上 Name 列每行有一个值,但 Colortype 可以有 0 到多个值。我的 SQL 中的问题是 ColorType 字段是一个由换行符 CHR(10) 分隔的值的 blob 列表。因此,在黄色名称下,颜色类型包含由换行符分隔的香蕉和金色。但您也可以看到 Name:Orange 也有 Gold 颜色类型。
在我的 SQL 结束时,我将单独的行汇总起来,以便最后得到一行,每列包含一个使用此值的列表。
SELECT distinct RTRIM(XMLAGG(XMLELEMENT(E, (myTableX.uo_unicode_to_sch (colortype)), CHR (10) ).EXTRACT('//text()') ORDER BY pct_vu).GetClobVal(),',') as risk_tx,
RTRIM(XMLAGG(XMLELEMENT(E, myTableY.uo_unicode_to_sch (name)), CHR(10)).EXTRACT('//text()') ORDER BY pct_vu desc).GetClobVal(),',') AS name
这给了我一行,它的名称已经是唯一的 19 个值。还有颜色类型,它是 1+x 非唯一值的列表。像这样,但不是单元格中值之间的空格,而是换行符。
姓名 | 颜色类型 |
---|---|
橙黄 | 金香蕉金 |
这是大部分原始sql:
SELECT *
FROM (SELECT distinct to_char(colortype), name
FROM (SELECT DISTINCT DBMS_LOB.substr(x.name, 4000) as name ,
DBMS_LOB.substr(x.colortype, 4000, 1) as colortype
FROM (SELECT distinct RTRIM(XMLAGG(XMLELEMENT(E, (myTableA.uo_unicode_to_A (colortype)), CHR (10) ).EXTRACT('//text()') ORDER BY w).GetClobVal(),',') as colortype,
RTRIM(XMLAGG(XMLELEMENT(E, myTableA.uo_unicode_to_A (name)|| ' ' || CASE WHEN w < 0.1 THEN '< 0.1' ELSE TRIM (TO_CHAR (w, CASE WHEN w < 1 THEN '0.9' ELSE '999'END)) END
|| '%', CHR (10)).EXTRACT('//text()') ORDER BY w desc).GetClobVal(),',') AS name,
RTRIM(XMLAGG(XMLELEMENT(E,CHR (13) , CHR (10) ).EXTRACT('//text()') ).GetClobVal(),',') AS rz
FROM (SELECT MAX (CASE WHEN z.item_type = 'Name' THEN z.value_tx END) AS name,
MAX (CASE WHEN z.item_type = 'Exact %' THEN TO_NUMBER(REGEXP_SUBSTR(z.value_tx,'^\d+')) END) AS w,
MAX (CASE WHEN z.item_type = 'Class' THEN z.value_tx END) AS colortype
FROM myTableA.product p
JOIN TABLE (myTableA.z_data.get_unique_name ('r@'|| TO_CHAR (p.prod_id)))z
ON z.country_cd = 'US' AND z.locale_cd = 'en' AND z.section_vu = 3
AND z.item_type IN ('Name','Exact %','Class')
GROUP BY z.sub_section_nm))x
JOIN TABLE (CAST (MULTISET(SELECT LEVEL FROM DUAL CONNECT BY LEVEL <=(LENGTH (x.colortype)- LENGTH (REPLACE (x.colortype,x.rz)))
/ LENGTH (x.rz) + 1) AS SYS.odcinumberlist)) y
ON 1 = 1
)
);
我无法提供完整的 sql,但我正在寻找的是任何人对最终如何区分 clob 字段的想法?我正在使用 12.1 甲骨文。
解决方案
以下两种方法都使用LISTAGG
,因此如果您的结果中包含超过 4000 个字符,您可能需要找到另一种聚合方法。
由于您使用的是 Oracle 12.1,因此您需要这样的查询:
WITH
colors
AS
(SELECT 'Orange' AS name, 'Gold' AS colortype FROM DUAL
UNION ALL
SELECT 'Yellow', 'Banana' || CHR (10) || 'Gold' FROM DUAL),
split_colors
AS
(SELECT name, COLUMN_VALUE AS color
FROM colors c
CROSS JOIN
TABLE (
CAST (
MULTISET (
SELECT SUBSTR (TRIM (REGEXP_SUBSTR (c.colortype,
'[^' || CHR (10) || ']+',
1,
LEVEL)),
1,
4000)
FROM DUAL
CONNECT BY LEVEL <=
REGEXP_COUNT (c.colortype, '[^' || CHR (10) || ']+'))
AS SYS.ODCIVARCHAR2LIST)) c1)
SELECT (SELECT LISTAGG (name, CHR (10)) WITHIN GROUP (ORDER BY name)
FROM (SELECT DISTINCT name
FROM split_colors)) AS names,
(SELECT LISTAGG (color, CHR (10)) WITHIN GROUP (ORDER BY color)
FROM (SELECT DISTINCT color
FROM split_colors)) AS colors
FROM DUAL;
如果您使用的是 Oracle 19c,则可以使用LISTAGG DISTINCT
WITH
colors
AS
(SELECT 'Orange' AS name, 'Gold' AS colortype FROM DUAL
UNION ALL
SELECT 'Yellow', 'Banana' || CHR (10) || 'Gold' FROM DUAL),
split_colors
AS
(SELECT name, COLUMN_VALUE AS color
FROM colors c
CROSS JOIN
TABLE (
CAST (
MULTISET (
SELECT SUBSTR (TRIM (REGEXP_SUBSTR (c.colortype,
'[^' || CHR (10) || ']+',
1,
LEVEL)),
1,
4000)
FROM DUAL
CONNECT BY LEVEL <=
REGEXP_COUNT (c.colortype, '[^' || CHR (10) || ']+'))
AS SYS.ODCIVARCHAR2LIST)) c1)
SELECT LISTAGG (DISTINCT name, CHR (10)) WITHIN GROUP (ORDER BY name) AS names,
LISTAGG (DISTINCT color, CHR (10)) WITHIN GROUP (ORDER BY color) AS colors
FROM split_colors;
推荐阅读
- javascript - 如何导入 @orange-games/phaser-ads 节点模块?
- java - Docker(Spring Boot 或 Thorntail)和 Keycloak
- c# - TemplateField ItemTemplate 仅在回发后显示
- php - 使用 CI 中的加载数据 InFile 上传 500000 条记录,但有时并非所有记录都插入
- javascript - 如何使用预填充数据验证文本区域?
- android - 当应用程序在后台时在推送通知中获取操作
- keen-io - .net 的敏锐 io 限制子句
- php - 处理引入类型提示导致的 PHP 致命类型错误
- php - 当他访问本地主机 URL“proj.test”时,将用户重定向到 HTTPS URL 而不是 HTTP
- jquery - 通过jquery调用表时替换字符串不起作用