用于组中任何非特定值的SQL聚合函数

用于组中任何非特定值的SQL聚合函数,sql,oracle,Sql,Oracle,是否有一个agregate函数可以从组中返回任何值。我可以使用MIN或MAX,但如果可能的话,我宁愿避免开销,因为它是一个文本字段 我的情况是一个错误日志摘要。错误按错误类型分组,并为每个组显示错误文本的示例。使用哪个错误消息作为示例并不重要 SELECT ref_code, log_type, error_number, COUNT(*) AS count, MIN(data) AS example FROM data GROUP BY ref_

是否有一个agregate函数可以从组中返回任何值。我可以使用
MIN
MAX
,但如果可能的话,我宁愿避免开销,因为它是一个文本字段

我的情况是一个错误日志摘要。错误按错误类型分组,并为每个组显示错误文本的示例。使用哪个错误消息作为示例并不重要

SELECT
    ref_code,
    log_type,
    error_number,
    COUNT(*) AS count,
    MIN(data) AS example
FROM data
GROUP BY
    ref_code,
    log_type,
    error_number

我可以用什么替换
MIN(数据)
,而不必比较100000 s的varchar(2000)值?

您可以使用MIN和KEEP,如下所示:

MIN(data) keep (dense_rank first order by rowid) AS EXAMPLE

这背后的想法是,数据库引擎将通过ROWID而不是VARCHAR(2000)值对数据进行排序,理论上,VARCHAR(2000)值应该更快。您可以将ROWID替换为主键值,并检查它是否更快。既然您询问了OVER PARTITION and ORDER BY,下面是一个版本,它可以按进行分组,但也可以使用带有OVER and PARTITION and ORDER BY的ROW_NUMBER()对第一个
ref_code,log_type,错误_num
它作为行号1出现的组合(在1处有任何数据列)。然后,从1开始,在它找到的下一个不同的
ref\u代码、log\u类型、error\u num
组合处重新编号(无论出现什么数据列)。因此,您可以简单地将第1行的数据字段作为给定
ref\u代码、log\u类型、error\u num
的代表性数据字段

它仍然缺少一些东西。如果我没有双通行证(一次用于聚合,一次用于行数()),它会更优雅;然而,它可能会表现得非常好。我得再考虑一下,看能不能取消双传球

但它避免了对大数据字段的任何比较。它代表了一种实现您所要求的方法:从数据字段中提取一个与聚合字段相关的代表性样本

SELECT
    t.ref_code,
    t.log_type,
    t.error_number,
    t.count,
    d.data
FROM
(
    SELECT
        ref_code,
        log_type,
        error_number,
        COUNT(*) as count
    FROM data
    GROUP BY
        ref_code,
        log_type,
        error_number
) t
INNER JOIN 
(
    SELECT
        ref_code,
        log_type,
        error_number,
        data,
        ROW_NUMBER() OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as row_number
    FROM data
) d on
    d.ref_code = t.ref_code and
    d.log_type = t.log_type and
    d.error_number = t.error_number and
    row_number = 1
最后一点警告:我没有甲骨文可以试穿。但我确实是通过阅读Oracle文档将其组合起来的


在我进一步思考了如何使用elminate组之后,我添加了下面的内容,我只在那里使用了COUNT(*)。但我不知道它是否更快

SELECT *
FROM
(
    SELECT
        ref_code,
        log_type,
        error_number,
        data,
        ROW_NUMBER() OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as row_number,
        COUNT(*) OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as count 

    FROM data
) t
WHERE row_number = 1

根据建议的答案,似乎
MIN(data)
(或
MAX(data)
)是实现我想要的最快方法。我试图过度乐观,这是不必要的

当我访问这个数据库时,我会尝试任何其他的答案,但同时,这是最重要的


谢谢大家的努力

看一看:
min()
max()
的开销最小。仅仅读取字符串会比比较逻辑产生更多的开销。@GordonLinoff,很高兴知道。但是,如果我想要的函数存在,它将消除每个组读取任何多于一行的文本的需要,这远远少于每个记录读取一行。@DWright,感谢您向我介绍
OVER
PARTITION BY
子句。我不知道如何使用它们从组中返回任意一条记录。谢谢!虽然它可以按预定的方式工作,但不幸的是,它的运行速度比简单的
MIN(data)
语句慢20%。至少这支持了我过度优化的理论。非常发人深省,但不幸的是,这一次大约慢了130%。尽管如此,我还是学到了很多关于更先进的SQL技术的知识,这些技术永远不会误入歧途。很酷,感谢您尝试了一下,很高兴了解性能下降的情况。顺便说一句,我不得不让团队留在那里的唯一原因是因为我不知道如何进行计数。不需要计数,我就可以从
SELECT ref\u code、log\u type、error\u number、data、ROW\u number()中获取所有信息(按参考代码、日志类型、错误编号顺序按参考代码、日志类型、错误编号划分)作为行编号,从行编号=1的数据中可以实际进行计数(*)超过
…,但我不得不做这样的改变,一个用于计数(*),一个用于排号()。在任何情况下,我补充说,作为我答案的替代方案,作为最后想法(评论)的结果,在原始答案下面。我很好奇性能如何?