max()和group by,需要整个结果的count(*)

dbf7pr2w  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(381)

我有一个 SELECT 我正在执行的查询 MAX() 列和a GROUP BY 子句,并且除了我需要返回给客户机的查询结果之外,我还需要返回所有结果的总计数。
基本上我的问题是:

SELECT unique_id, col1, col2, MAX(col3) as col3
FROM tbl
GROUP BY col1, col2

通常会有一个 WHERE 条款也是。
这个 unique_id 是表的主键。
在将此数据返回给客户机时,我还指定 LIMIT 以及 OFFSET 子句来限制一次检索的结果数。我的问题是,如果上面的查询没有 LIMIT 以及 OFFSET 子句,以便客户端可以稍后/增量地检索其余的。
我知道我可以很容易地使用 WITH 临时表以获得我想要的:

WITH temp AS (
    SELECT unique_id, col1, col2, MAX(col3) as col3
    FROM tbl
    GROUP BY col1, col2
)
SELECT count(*) FROM temp

但我很担心这个的效率。sans- LIMIT -以及- OFFSET 查询可能返回数万行,所以我认为 WITH 获取总计数的方法并不是最好的方法。
有没有更有效的方法,我没有想到?或者是 WITH 方法(例如,mysql服务器是否足够聪明,不需要分配整个查询结果集来获得计数)?

示例数据

假设这是我表中的数据:

unique_id  col1  col2  col3
___________________________
1          5     8     30
2          5     8     33
3          5     9     40
4          6     8     30
5          6     8     31
6          6     8     32
7          6     9     39
8          7     8     33
9          7     8     32
10         8     8     34

所以我的 SELECT 查询将返回这个(假设指定的客户端 LIMIT 4 OFFSET 0 ):

SELECT unique_id, col1, col2, max(col3) as col3
FROM tbl
GROUP BY col1, col2
LIMIT 4
OFFSET 0;
    unique_id  col1  col2  col3
    ___________________________
    2          5     8     33
    3          5     9     40
    6          6     8     32
    7          6     9     39

然后我就不用 LIMIT 以及 OFFSET 子句作为子查询和 SELECT COUNT(*) 从它那里,它会回来 6 ,我会把 6 把结果告诉客户。

8qgya5xd

8qgya5xd1#

mysql 8引入了对窗口函数的支持,包括窗口聚合函数。窗口聚合函数允许您将聚合结果与非聚合数据一起返回。基本上,您可以通过附加 OVER 但通常还需要指定其他选项,这在链接的手册中有详细说明。
可以在中使用窗口聚合函数 GROUP BY 我也是。在这些情况下,窗口聚合函数将在分组完成后应用于行集。还要注意的是 LIMIT 不会影响窗口聚合函数的结果。
考虑到以上所有因素,您可以这样修改原始查询:

SELECT
  unique_id,
  col1,
  col2,
  MAX(col3) as col3,
  COUNT(*) OVER () AS TotalRows
FROM
  tbl
GROUP BY
  col1,
  col2
LIMIT
  4 OFFSET 0
;

并一次性获得原始细节数据和行数。这个 OVER 子句没有其他子类,这意味着它应用于整个行集。
如前所述,窗口聚合函数将忽略 LIMIT 子句,如果查询附加了一个。因此 TotalRows 上面的列将反映行数,就好像没有应用限制一样。

相关问题