我正在与两个实体合作:Item
和 Attribute
, 如下所示:
Item
----
itemId
Attribute
---------
attributeId
name
安
Item
有 Attributes
,如关联表中所指定:ItemAttribute
--------------
itemId
attributeId
当此数据到达客户端时,它将显示为每
Item
一行。 , 每行都会有一个 Attribute
的列表s 的名字。例如:Item Attributes
---- ----------
1 A, B, C
2 A, C
3 A, B
用户可以选择对
Attributes
进行排序。列,因此我们需要能够按如下方式对数据进行排序:Item Attributes
---- ----------
3 A, B
1 A, B, C
2 A, C
目前,我们每
ItemAttribute
获取一行数据排。基本上: SELECT Item.itemId,
Attribute.name
FROM Item
JOIN ItemAttribute
ON ItemAttribute.itemId = Item.itemId
JOIN Attribute
ON Attribute.attributeId = ItemAttribute.attributeId
ORDER BY Item.itemId;
产生的结果如下:
itemId name
------ ----
1 A
1 B
1 C
2 A
2 C
3 A
3 B
实际
ORDER BY
子句基于用户输入。通常是单列,所以排序比较简单,处理结果集的app端循环结合了Attribute
名称转换为逗号分隔的列表,以便在客户端上显示。但是当用户要求对该列表进行排序时,最好让 Oracle 对结果进行排序,这样——使用上面的例子——我们会得到:itemId name
------ ----
3 A
3 B
1 A
1 B
1 C
2 A
2 C
甲骨文
LISTAGG
函数可用于在排序之前生成属性列表;然而 Attribute.name
可以是很长的字符串,并且组合列表有可能大于4000个字符,这会导致查询失败。是否有一种干净、有效的方式使用 Oracle SQL (11gR2) 以这种方式对数据进行排序?
最佳答案
这里真的有两个问题:
1)如何聚合超过4000个字符的数据
聚合这么多数据并将其显示在单列中是否明智?
无论如何,您将需要某种大型结构来显示超过 4000 个字符,例如 CLOB
例如。您可以按照 Tom Kyte's thread 之一中描述的一般准则编写自己的聚合方法。 (显然您需要修改它,以便最终输出是一个 CLOB)。
我将演示一个带有嵌套表和自定义函数的更简单的方法(适用于 10g):
SQL> CREATE TYPE tab_varchar2 AS TABLE OF VARCHAR2(4000);
2 /
Type created.
SQL> CREATE OR REPLACE FUNCTION concat_array(p tab_varchar2) RETURN CLOB IS
2 l_result CLOB;
3 BEGIN
4 FOR cc IN (SELECT column_value FROM TABLE(p) ORDER BY column_value) LOOP
5 l_result := l_result ||' '|| cc.column_value;
6 END LOOP;
7 return l_result;
8 END;
9 /
Function created.
SQL> SELECT item,
2 concat_array(CAST (collect(attribute) AS tab_varchar2)) attributes
3 FROM data
4 GROUP BY item;
ITEM ATTRIBUTES
1 a b c
2 a c
3 a b
2)如何对大数据进行排序不幸的是,您不能在 Oracle 中按任意大的列进行排序:相对于排序键的类型和长度,存在已知的限制。
ORA-00932
:不一致的数据类型:预期 - 得到 CLOB。 ORA-06502
: PL/SQL: 数字或值错误:字符串缓冲区太小 我建议您按属性列的前 4000 个字节排序:
SQL> SELECT * FROM (
2 SELECT item,
3 concat_array(CAST (collect(attribute) AS tab_varchar2)) attributes
4 FROM data
5 GROUP BY item
6 ) order by dbms_lob.substr(attributes, 4000, 1);
ITEM ATTRIBUTES
3 a b
1 a b c
2 a c
关于sql - 在没有 LISTAGG 的 Oracle SQL 中按字符串列表排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11541383/