这是一个在oracle中聚合字符串的自定义函数。
Date Fruit Number
1 Apple 1
1 Apple 4
1 Apple 3
1 Kiwi 6
1 Kiwi 10
转向
Date Fruit Number
1 Apple 1-3-4
1 Kiwi 6-10
使用
SELECT Date,fruit, string_agg(number) AS Agg
FROM fruit
GROUP BY Date,fruit
string_agg是由下面的代码创建的函数
CREATE OR REPLACE TYPE t_string_agg AS OBJECT
(
g_string VARCHAR2(32767),
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_string_agg)
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_string_agg,
value IN VARCHAR2 )
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_string_agg,
returnValue OUT VARCHAR2,
flags IN NUMBER)
RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_string_agg,
ctx2 IN t_string_agg)
RETURN NUMBER
);
/
SHOW ERRORS
CREATE OR REPLACE TYPE BODY t_string_agg IS
STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_string_agg)
RETURN NUMBER IS
BEGIN
sctx := t_string_agg(NULL);
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_string_agg,
value IN VARCHAR2 )
RETURN NUMBER IS
BEGIN
SELF.g_string := self.g_string || ',' || value;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate(self IN t_string_agg,
returnValue OUT VARCHAR2,
flags IN NUMBER)
RETURN NUMBER IS
BEGIN
returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_string_agg,
ctx2 IN t_string_agg)
RETURN NUMBER IS
BEGIN
SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
RETURN ODCIConst.Success;
END;
END;
/
SHOW ERRORS
CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)
RETURN VARCHAR2
PARALLEL_ENABLE AGGREGATE USING t_string_agg;
/
SHOW ERRORS
但问题是我不能按照我希望的方式按顺序排序字符串。如何修改自定义函数代码以按照数字或类似的顺序按特定顺序进行聚合?
顺便说一句:我的版本是10g,所以我不能使用listagg。可以修改此代码以便通过某个输入进行排序吗?谢谢!
答案 0 :(得分:0)
不要重新发明轮子。使用 LISTAGG
:
CREATE TABLE tab("Date" INT, Fruit VARCHAR(100), "Number" INT);
INSERT INTO tab VALUES (1 ,'Apple', 1);
INSERT INTO tab VALUES (1 ,'Apple', 4);
INSERT INTO tab VALUES (1 ,'Apple', 3);
INSERT INTO tab VALUES (1 ,'Kiwi', 6);
INSERT INTO tab VALUES (1 ,'Kiwi', 10);
SELECT DISTINCT "Date", Fruit,
LISTAGG ("Number" , '-')
WITHIN GROUP (ORDER BY "Date") OVER(PARTITION BY "Date", Fruit) AS "Number"
FROM tab;
的 SqlFiddleDemo
强>
警告:的
请注意,您需要ORDER BY
列。在这种情况下,如果查询将以不同的顺序读取数据,则您不会使用升序orde的列并使用具有所有相同值的Date
。你应该有类似的东西:
ID Date Fruit Number
1 1 Apple 1
2 1 Apple 4
3 1 Apple 3
4 1 Kiwi 6
5 1 Kiwi 10
和
LISTAGG ("Number" , '-')
WITHIN GROUP (ORDER BY ID ASC) OVER(PARTITION BY "Date", Fruit) AS "Number"
修改强>
LISTAGG
可从 Oracle 11 获取