是否有一个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(data)
代替什么,而不必比较100,000的varchar(2000)值?
答案 0 :(得分:4)
你可以使用MIN加上KEEP,如下所示:
MIN(data) keep (dense_rank first order by rowid) AS EXAMPLE
这背后的想法是数据库引擎将通过ROWID而不是VARCHAR(2000)值对数据进行排序,理论上应该更快。您可以使用主键值替换ROWID,并检查它是否更快
答案 1 :(得分:3)
根据提议的答案,MIN(data)
(或MAX(data)
)似乎是达到我想要的最快方式。我试图不必要地进行过度优化。
我可以尝试在访问此数据库时出现的任何其他答案,但与此同时,这也是最重要的。
感谢大家的努力!
答案 2 :(得分:2)
好吧,既然你问过OVER PARTITION和ORDER BY,下面是一个版本,你的GROUP BY,但是也使用ROW_NUMBER()和OVER和PARTITION AND ORDER BY来编号第一个ref_code, log_type, error_num
组合它出现在行号1(任何数据列都在1)。然后它从1开始重新编号,找到它找到的下一个不同的ref_code, log_type, error_num
组合(无论发生在那里的任何数据列)。因此,您可以简单地将第1行的数据字段作为给定ref_code, log_type, error_num
的代表性数据字段。
它还缺少某些东西。如果我没有双遍(一次用于聚合,一次用于row_number()),它会更优雅;然而,它可能表现得非常好。我将不得不考虑更多,看看我是否可以消除双通。
但它避免了对大数据字段的任何比较。它代表了一种方法来做你所要求的:从数据字段中提取1个代表性样本与聚合字段相关联。
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试试这个。但我确实从阅读Oracle文档中把它放在一起。
在我进一步思考如何消除GROUP BY之后,我添加了以下内容,我在那里只有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