首页 > 解决方案 > 聚合函数作为元组参数 postgres

问题描述

我想使用元组将聚合函数(如 min、max 等)作为查询参数传递。

以下是我的查询:

"select  $5(CAST (vol AS FLOAT)) AS agg_v, " 
                    + "time_bucket_gapfill" + "(($1::text || ' minutes')::interval, t) AS time_function_minute, " 
                    + "tag_id from rtdata "
                    + "where tag_id = any($2) and t > $3 and t < $4 "
                    + "GROUP BY (tag_id, time_function_minute) ORDER BY time_function_minute"

但我得到以下异常:

io.vertx.pgclient.PgException:io.vertx.pgclient.impl.codec.ErrorResponse.toException(ErrorResponse.java:29) 在 io.vertx.pgclient.impl.codec.PrepareStatementCommandCodec 处或附近出现语法错误。 handleErrorResponse(PrepareStatementCommandCodec.java:62) at io.vertx.pgclient.impl.codec.PgDecoder.decodeError(PgDecoder.java:233) at io.vertx.pgclient.impl.codec.PgDecoder.decodeMessage(PgDecoder.java:122)在 io.vertx.pgclient.impl.codec.PgDecoder.channelRead(PgDecoder.java:102) 在 io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) 在 io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext .java:374) 在 io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) 在 io.netty.channel.AbstractChannelHandlerContext。fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel .AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) 在 io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) 在 io.netty.channel.nio.NioEventLoop.processSelectedKeys( NioEventLoop.java:552) 在 io.netty.channel.nio.NioEventLoop。在 io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) 在 io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) 在 io 运行(NioEventLoop.java:514) .netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) 在 java.lang.Thread.run(Thread.java:745)

但是如果我用硬编码聚合函数替换 $5 它就可以了。在这种情况下如何动态传递聚合函数?

RxJava 代码片段:

return txBegin()
                .flatMapObservable(tx -> 
                    tx.rxPrepare(abovesql)
                    .flatMapObservable(pq -> {
                        return pq.createStream(50, 
                                                Tuple.of(
                                                    evalBucketInterval(req),
                                                    req.getTags().toArray(new Integer[0]),
                                                    parse(req.getStartDate()), 
                                                    parse(req.getEndDate()),
                                                    parse(req.getAggFunc())))
                                    .toObservable();
                    })
                .doAfterTerminate(tx::commit))
            .map(this::toFuncJson);

标签: postgresqlaggregate-functionsrx-java2vert.xtimescaledb

解决方案


PostgreSQL 只允许将参数用作值,并且在您尝试将参数用于函数名、表名等时不理解。因此您不能将聚合名称作为参数传递。

我建议通过连接包含聚合函数名称的字符串值在您的应用程序中解决它。我想它可能是这样的,但我不确定确切的语法以及您的环境有哪些限制:

"select  "+ my_agg_func_name +"(CAST (vol AS FLOAT)) AS agg_v, " 
                    + "time_bucket_gapfill" + "(($1::text || ' minutes')::interval, t) AS time_function_minute, " 
                    + "tag_id from rtdata "
                    + "where tag_id = any($2) and t > $3 and t < $4 "
                    + "GROUP BY (tag_id, time_function_minute) ORDER BY time_function_minute"

推荐阅读