当前位置: 首页 > 知识库问答 >
问题:

获取每个组的计数,但在每个组中的N个结果行之后停止计数

越飞语
2023-03-14

我正在尝试优化一个查询,这个查询(不必要地)在一个表中计算将近90万行,这花费了太长的时间。

该表包含发生在web应用程序不同部分的事件的日志条目,我想知道当每种日志类型的行计数为1000或更少时,该类型存在多少未读日志条目,但如果计数为1001或更多,则最多计算1001行。

之后我就不需要再数了,我只会为那个日志类型输出“超过1000”。

假设我们有下表my_logs,其中包含数据:

id    log_type    log_text   is_read
1     'Type 1'    'Text 1'   1
2     'Type 1'    'Text 2'   1
3     'Type 1'    'Text 3'   0
4     'Type 1'    'Text 4'   0
5     'Type 1'    'Text 5'   0
6     'Type 1'    'Text 6'   0
7     'Type 2'    'Text 7'   0
8     'Type 2'    'Text 8'   0

在本例中,我的当前查询如下所示:

选择log_type,从my_logs中将(*)计数为未读,其中is_read=0 GROUP BY log_type;

该查询对每一行进行计数,并给出每种日志类型的正确行数。 问题是,当表包含90万行时,这是一个昂贵的查询,每种类型的行数超过1000行是完全没有必要的,因为用户不会在意1 000和20 000之间的差别,他们只会看到很多条目。

这是我得到的最接近解决方案(限制调整为适合my_logs示例和演示用法):

SELECT log_type, COUNT(*) AS unread
FROM (
    SELECT log_type
    FROM my_logs ml1
    WHERE is_read = 0
    LIMIT 3 /* To display "more than 2" in webapp */
) AS ml2
GROUP BY logtype_txt;

但是该查询将内部查询中的所有log_type集合在一起,并将其限制为1001行,这不是我想要的。 我需要将行拆分为每个log_type,然后计算最多1001行。 在本例中,我想要的输出是:

log_type    unread
'Type 1'    3
'Type 2'    2

这道题和这道题讨论了当找到n行时如何停止计数,但不要考虑到我需要的分组。

有人知道解决办法吗?

共有1个答案

虞安康
2023-03-14

这个答案在MariaDB或MySQL中不起作用。

你要找的答案是基于一个“侧向表表达式”。 这是在Oracle,DB2,PostgreSQL和SQL Server中实现的。

以下是PostgreSQL中从表中读取行的最佳查询:

select x.log_type, count(y.z)
from (
  select distinct log_type as log_type
  from my_log
) x
left join lateral (
  select 1 as z
  from my_log b 
  where b.log_type = x.log_type and is_read = 0
  limit 2 + 1
) y on true
group by x.log_type

参见DB Fiddle中的运行示例。

横向查询根据放在它们前面的表表达式上的可用值执行一次。 在本例中,表表达式x将为log_type生成所有不同的值(使用索引来实现性能)。 然后横向查询将针对x中的每个值执行一次,限制为3(在本例中)。 最后,查询会计算遇到多少z值。

如您所见,上面的进程最多只读取每个类型的3行。

 类似资料:
  • 返回数组中的每个第 n 个元素。 使用 Array.filter() 创建一个包含给定数组的每个第 n 个元素的新数组。 const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); everyNth([1, 2, 3, 4, 5, 6], 2); // [ 2, 4, 6 ]

  • 问题内容: 所以我查了一下,这个问题非常相似,但是它缺少一个关键点:SQL Server计算表的每一列中不同值的数量 因此,在这个问题中,他们希望每列的计数都不同。我想要做的是获取表中每个列的每个不同值的计数(而我正在为特定数据库中的所有表执行此操作,这就是为什么我要尝试尽可能地自动化这一点的原因尽可能)。当前,我的代码看起来像这样,我必须为每一列运行: 理想情况下,我的输出应如下所示: 以此类推

  • 问题内容: 我有一个简单的表,像这样: 我想获得每个用户出现的前2个“字母”, 甚至更好:崩溃成列 我怎样才能在postgres中做到这一点? 问题答案: = > SQL小提琴演示

  • 问题内容: 我有一张表格,我想获取每个组的最新条目。这是桌子: 桌子 该表将按降序分组并按降序排序。对于每个,我想获取最新状态。 我的首选输出: 是否有任何汇总函数只能从每个组中获得最高排名?请参阅下面的伪代码: DocumentID, GetOnlyTheTop(Status), GetOnlyTheTop(DateCreated) FROM DocumentStatusLogs GROUP B

  • 问题内容: 我如何能够在oracle查询中为几个组获得N个结果。 例如,给定下表: 有更多行和更多职业。我想从每个职业中聘请三名员工(可以说)。 有没有不用子查询就可以做到这一点的方法? 问题答案: 这将产生所需的内容,并且不使用供应商特定的SQL功能(例如TOP N或RANK())。 在此示例中,它为三位雇员提供每个职业emp_id最低的值。您可以更改不等式比较中使用的属性,以使其按名称或其他方

  • 问题内容: 以下是最简单的示例,尽管任何解决方案都应能够扩展到需要n个顶级结果的地方: 给定下面的表格,其中包含“人员”,“组”和“年龄”列,您将如何 获得每个组中 年龄 最大的2个人? (组内的关系不应产生更多结果,而应按字母顺序给出前两个) 所需的结果集: 注意: 这个问题建立在先前的问题上- 获取每组分组的SQL结果的最大值的记录 -用于从每组中获取一个顶行,并且从@Bohemian那里收到

  • 问题内容: 有什么方法可以计算数组中每个项目的出现? 可以说我有: 这里的输出将是: 如果我有: 输出为: 这里的输出只是为了展示预期的结果。 问题答案: 你可以使用来自Google Collections / Guava的或来自Apache Commons的。 如果你有一个集合而不是一个数组,则可以用于addAll()将整个内容添加到上述数据结构中,然后将该方法应用于每个值。一个或会给你以定义的

  • 有没有一种方法可以简化或使R代码更优雅?