Vertica 数据库实现LISTAGG 聚合函数

通过改造例子中的 Concatenate 实现。

/* Copyright (c) 2005 - 2015 Hewlett Packard Enterprise Development LP -*- C++ -*- */
/* 
 * Description: Example User Defined Aggregate Function: ListAgg strings
 *
 */

#include "Vertica.h"
#include <time.h> 
#include <sstream>
#include <iostream>

using namespace Vertica;
using namespace std;


/**
 * User Defined Aggregate Function ListAgg that takes in strings and concatenates
 * them together. Right now, the max length of the resulting string is ten times the
 * maximum length of the input string.
 */
class ListAgg : public AggregateFunction
{

	
	
    virtual void initAggregate(ServerInterface &srvInterface, IntermediateAggs &aggs)
    {
	   
	    
		
		//初始化聚合函数返回结果
        try {
            VString &concat = aggs.getStringRef(0);
            concat.copy("");
        } catch(exception& e) {
            // Standard exception. Quit.
            vt_report_error(0, "Exception while initializing intermediate aggregates: [%s]", e.what());
        }
    }

    void aggregate(ServerInterface &srvInterface, 
                   BlockReader &argReader, 
                   IntermediateAggs &aggs)
    {
	
	//获取分割字符串
	    // Get the value of splitstr from the parameters
        ParamReader paramReader = srvInterface.getParamReader();
        if (!paramReader.containsParameter("splitstr")) {
            vt_report_error(0, "You must provide a value for parameter splitstr");
        }
        VString splitstr = paramReader.getStringRef("splitstr");
	
	
        try {
            VString &concat = aggs.getStringRef(0);
            string word = concat.str();
            uint32 maxSize = aggs.getTypeMetaData().getColumnType(0).getStringLength();
            do {
                const VString &input = argReader.getStringRef(0);
                if (!input.isNull()) {
                    if ((word.length() + input.length()+splitstr.length()) > maxSize) break;//不能超过最大长度
					
                    word.append(input.str());
					word.append(splitstr.str());
                }
            } while (argReader.next());
            concat.copy(word);
        } catch(exception& e) {
            // Standard exception. Quit.
            vt_report_error(0, "Exception while processing aggregate: [%s]", e.what());
        }
    }

    virtual void combine(ServerInterface &srvInterface, 
                         IntermediateAggs &aggs, 
                         MultipleIntermediateAggs &aggsOther)
    {
	    // Get the value of splitstr from the parameters
        ParamReader paramReader = srvInterface.getParamReader();
        if (!paramReader.containsParameter("splitstr")) {
            vt_report_error(0, "You must provide a value for parameter splitstr");
        }
        VString splitstr = paramReader.getStringRef("splitstr");
		
        try {
            uint32 maxSize = aggs.getTypeMetaData().getColumnType(0).getStringLength();
            VString myConcat = aggs.getStringRef(0);

            do {
                const VString otherConcat = aggsOther.getStringRef(0);
                if ((myConcat.length() + otherConcat.length()+splitstr.length()) <= maxSize) {
                    string word = myConcat.str();
                    word.append(otherConcat.str());
					//word.append(splitstr.str());
                    myConcat.copy(word);
                }
            } while (aggsOther.next());
        } catch(exception& e) {
            // Standard exception. Quit.
            vt_report_error(0, "Exception while combining intermediate aggregates: [%s]", e.what());
        }
    }

    virtual void terminate(ServerInterface &srvInterface, 
                           BlockWriter &resWriter, 
                           IntermediateAggs &aggs)
    {
	     // Get the value of splitstr from the parameters
        ParamReader paramReader = srvInterface.getParamReader();
        if (!paramReader.containsParameter("splitstr")) {
            vt_report_error(0, "You must provide a value for parameter splitstr");
        }
        VString splitstr = paramReader.getStringRef("splitstr");
        try {
            const VString &concat = aggs.getStringRef(0);
			
			
            VString &result = resWriter.getStringRef();
            
            result.copy(concat.str().substr(0,concat.length()-splitstr.length())); //截断最后的splitstr
        } catch(exception& e) {
            // Standard exception. Quit.
            vt_report_error(0, "Exception while computing aggregate output: [%s]", e.what());
        }
    }

    InlineAggregate()
};


class ListAggFactory : public AggregateFunctionFactory
{
    virtual void getIntermediateTypes(ServerInterface &srvInterface, const SizedColumnTypes &inputTypes, SizedColumnTypes &intermediateTypeMetaData)
    {
        int input_len = inputTypes.getColumnType(0).getStringLength();
        intermediateTypeMetaData.addVarchar(input_len*10);
    }

    virtual void getPrototype(ServerInterface &srvfloaterface, ColumnTypes &argTypes, ColumnTypes &returnType)
    {
        argTypes.addVarchar();//输入函数字符串类型(聚合函数只能一个参数 ,只能使用 using parameters 增加额外参数)
        returnType.addVarchar();
    }

    virtual void getReturnType(ServerInterface &srvfloaterface, 
                               const SizedColumnTypes &inputTypes, 
                               SizedColumnTypes &outputTypes)
    {
        int input_len = inputTypes.getColumnType(0).getStringLength();
        outputTypes.addVarchar(input_len*10);
    }
	
	virtual void getParameterType(ServerInterface &srvInterface,
                                  SizedColumnTypes &parameterTypes)
    {
        parameterTypes.addVarchar(10,"splitstr");//额外参数,使用 using parameters 增加额外参数
    }

    virtual AggregateFunction *createAggregateFunction(ServerInterface &srvfloaterface)
    { return vt_createFuncObject<ListAgg>(srvfloaterface.allocator); }

};

RegisterFactory(ListAggFactory);


测试例子


select DEALER_CD ,public.LISTAGG(TPTYPE   using parameters splitstr=',') as TPTYPE   from (
SELECT distinct 
    DEALER_CD,
   trim( TPTYPE) TPTYPE
FROM
    DW.F_CR_EXIST_CUSTOMER
    where trim( TPTYPE)!=''
)t group by DEALER_CD

输入图片说明

猜你喜欢

转载自my.oschina.net/yjwu/blog/1627244
今日推荐