Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 当查询有GROUP BY时,如何获取总数的百分比?_Mysql_Sql - Fatal编程技术网

Mysql 当查询有GROUP BY时,如何获取总数的百分比?

Mysql 当查询有GROUP BY时,如何获取总数的百分比?,mysql,sql,Mysql,Sql,假设我有一个非标准化的表,其中有电影演员的名字和他们看过的电影。例如 CREATE TABLE movies_actors ( movies_actors_id INT, movie VARCHAR(255), actor VARCHAR(255), PRIMARY KEY (movies_actors_id) ); 我做了一个演员选择,从电影演员组中按演员数一,以了解演员已经拍了多少部电影。但我也想知道这位演员在电影中所占的比例 我想我可以做到: SELECT actor

假设我有一个非标准化的表,其中有电影演员的名字和他们看过的电影。例如

CREATE TABLE movies_actors (
  movies_actors_id INT,
  movie VARCHAR(255),
  actor VARCHAR(255),
  PRIMARY KEY (movies_actors_id)
);
我做了一个演员选择,从电影演员组中按演员数一,以了解演员已经拍了多少部电影。但我也想知道这位演员在电影中所占的比例

我想我可以做到:

SELECT
  actor,
  COUNT(1) AS total,
  COUNT(1) / (SELECT COUNT(1) FROM movies_actors) * 100 AS avg
FROM movies_actors
GROUP BY actor;
但这似乎。。。idk。。。恶心


有什么想法吗?

对于大型集合,联接可能比子查询执行得更好

SELECT ma.actor
     , COUNT(1) AS total
     , COUNT(1) / t.cnt * 100 AS `percentage`
  FROM movies_actors ma
 CROSS
  JOIN (SELECT COUNT(1) AS cnt FROM movies_actors) t
 GROUP
    BY ma.actor
     , t.cnt  
对于大型集合,并且当返回大量行时,联接操作的性能通常优于子查询。在您的例子中,它不是一个相关的子查询,所以MySQL不需要执行多次,所以它可能没有任何区别


给COUNT1的非粉丝们的提示。。。我们可以用COUNT*或IFNULLSUM1,0替换COUNT1的任何和所有实例,以获得相同的结果。

我不确定这是否更好,但您可以进行求和,然后在其他地方进行计算:

SELECT actor,
    COUNT(1) AS total,
    SUM(oneMoviePercentPts) AS percentage
FROM movies_actors
CROSS JOIN 
(
    SELECT 100 / CAST(COUNT(1) AS DECIMAL(15,4)) AS oneMoviePercentPts 
    FROM movies_actors
) t
GROUP BY actor

我希望MySQL优化器足够聪明,不会多次执行子查询,但联接语法使其更为明确。

只要您想从同一个表中获取经过处理的数据,就进行自交叉联接

SELECT
m.actor,
COUNT(m.actor) AS total,
(COUNT(m.actor) / t.total_movies) * 100 AS avg
FROM movies_actors m
cross (select count(*) as total_movies from movies_actors) t
GROUP BY m.actor;

不使用联接和多重查询:-

select actor,counter,  100 * counter / @total as percentage
from(
select actor, 
        case when actor is null
            then @total := count(*)
            else count(*)
        end as counter
    from movies_actors 
    group by actor
    with rollup
) mytable
这对我很有用:

SELECT tmpTotal.yearmonth, tmpTotal.rec_count, 
      (tmpTotal.rec_count / @myCumul) * 100 AS myPercentage
FROM
(
  SELECT tmpResult.*, @myCumul := @myCumul + tmpResult.rec_count AS myNewCumul
  FROM
  (
    SELECT date_format(d.created_at, '%Y/%m') as yearmonth, count(*) rec_count
    FROM cf4a_webapp.factTable d 
      join cf4a_webapp.dimTable c on (d.client_id = c.id)
    WHERE c.id = 25 
      AND d.created_at >= '2019-01-01 00:00:01' 
      AND d.created_at < '2020-01-01 00:00:01'
    GROUP BY yearmonth
  ) tmpResult
  JOIN (SELECT @myCumul := 0) tmpCumul
) tmpTotal;

需要注意的是,由于MySQL引擎的工作方式,count*的性能将与count1完全相同,而且在我看来,在语义上更为正确。SELECT list的表达式3不在GROUP BY子句中,并且包含未聚合的列“t.cnt”,它在功能上不依赖GROUP BY子句中的列;这与sql\u mode=only\u full\u组不兼容_by@brahimm:要使语句兼容,只需将t.cnt添加到GROUPBY子句。也就是说,由ma.actor,t.cnt组成的小组。内联视图派生的表t保证在成功运行时只返回一行,否则将抛出错误。