想知道是否有一种方法可以在一个 MySQL 查询中编写以下内容。
我有一张桌子: cust_ID | rpt_name | req_secs
在查询中我想得到:
按 cust_ID 分组时的 AVG req_secs
按 rpt_name 分组时的 AVG req_secs
总 req_secs AVG
我知道我可以对同一张表进行单独的分组查询,然后将结果合并为一个。但我希望有某种方法可以在一个查询中做到这一点。
谢谢。
好吧,以下将做三分之二:
select n,
(case when n = 1 then cast(cust_id as varchar(255)) else rpt_name end) as grouping,
avg(req_secs)
from t cross join
(select 1 as n union all select 2
) n
group by n, (case when n = 1 then cust_id else rpt_name end);
这基本上将数据“加倍”,然后对每个组进行聚合。这假定cust_id
和rpt_name
是兼容的类型。(如果不是这种情况,可以调整查询。)
实际上,您可以使用以下方法获得总体平均值rollup
:
select n,
(case when n = 1 then cust_id else rpt_name end) as grouping,
avg(req_secs)
from t cross join
(select 1 as n union all select 2
) n
group by n, (case when n = 1 then cast(cust_id as varchar(255)) else rpt_name end) with rollup
这适用于平均值,因为“加倍”数据的平均值与原始数据的平均值相同。它不适用于sum()
or count()
。
不,那里没有。您可以同时按 cust_ID 和 rpt_name 的组合进行分组(即两级分组),但您不能同时进行单独的顶级分组和非分组聚合。
由于 GROUP BY 的工作方式,执行此操作的 SQL 有点棘手。获得结果的一种方法是获取行的三个副本,并将每组行分别分组。
SELECT g.gkey
, IF(g.grp='cust_id',t.cust_ID,IF(g.grp='rpt_name',t.rpt_name,'')) AS gval
, AVG(t.req_secs) AS avg_req_secs
FROM (SELECT 'cust_id' AS gkey UNION ALL SELECT 'rpt_name' UNION ALL SELECT 'total') g
CROSS
JOIN mytable t
GROUP
BY g.gkey
, IF(g.grp='cust_id',t.cust_ID,IF(g.grp='rpt_name',t.rpt_name,''))
别名为“”的内联视图g
不必使用 UNION ALL 运算符,您只需要一个恰好返回 3 行具有不同值的行集。我只是使用 UNION ALL 作为将三个文字值作为行集返回的便捷方式,因此我可以将其加入到原始表中。