使用 group by 子句优化 MySQL 查询

标签 mysql sql query-optimization

我想根据国家、合作伙伴和零售商计算总点击次数和唯一点击次数。 我已经达到了预期的结果,但我认为这不是最佳解决方案,对于更长的数据集,它需要更长的时间。我该如何改进这个查询? 这是我的测试表、设计的查询和预期的输出:

"country_id","partner","retailer","id_customer","id_clickout"
"1","A","B","100","XX"
"1","A","B","100","XX"
"2","A","B","100","XX"
"2","A","B","100","GG"
"2","A","B","100","XX"
"2","A","B","101","XX"

DROP TABLE IF EXISTS x;
CREATE TEMPORARY TABLE x AS
SELECT test1.country_id, test1.partner,test1.retailer, test1.id_customer, 
SUM(CASE WHEN test1.id_clickout IS NULL THEN 0 ELSE 1 END) AS clicks,
CASE WHEN test1.id_clickout IS NULL THEN 0 ELSE 1 END AS unique_clicks
FROM test1
GROUP BY 1,2,3,4
;
SELECT country_id,partner,retailer, SUM(clicks), SUM(unique_clicks)
FROM x
GROUP BY 1,2,3

输出:

"country_id","partner","retailer","SUM(clicks)","SUM(unique_clicks)"
"1","A","B","2","1"
"2","A","B","4","2"

这是 DDL 和输入数据:

CREATE TABLE test (
 country_id INT(11) DEFAULT NULL,
 partner VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL,
 retailer VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL,
 id_customer BIGINT(20) DEFAULT NULL,
 id_clickout VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL)
  ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO test VALUES(1,'A','B','100','XX'),(1,'A','B','100','XX'),
            (2,'A','B','100','XX'),(2,'A','B','100','GG'),
            (2,'A','B','100','XX'),(2,'A','B','101','xx')

最佳答案

SELECT
  country_id,
  partner,
  retailer,
  COUNT(id_clickout)   AS clicks,
  COUNT(DISTINCT CASE WHEN id_clickout IS NOT NULL THEN id_customer END) AS unique_clicks
FROM
  test1
GROUP BY
  1,2,3
;

COUNT(a_field) 不会计算任何 NULL 值。

因此,COUNT(id_clickout) 只会计算它为NOT NULL 的次数。

同样,unique_clicks 中的CASE WHEN 语句只返回他们点击的记录的id_customer,否则返回NULL 。这意味着 COUNT(DISTINCT CASE) 仅计算不同的客户,并且仅在他们点击时计算。

编辑:

我刚刚意识到,它可能比那更简单...

SELECT
  country_id,
  partner,
  retailer,
  COUNT(*)                    AS clicks,
  COUNT(DISTINCT id_customer) AS unique_clicks
FROM
  test1
WHERe
  id_clickout IS NOT NULL
GROUP BY
  1,2,3
;

结果中唯一的实质性区别是,以前显示为 0 次点击 的任何 country_id, partner, retailed 现在根本不会出现在结果中。

使用 country_id, partner, retailed, id_clickout, id_customercountry_id, partner, retailed, id_customer, id_clickout 上的 INDEX,但是,此查询应该明显更快。

关于使用 group by 子句优化 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23424760/

相关文章:

sql - 更改查询计划

php - 使用 PHP 时区偏移

MySQL - 将 NULL 或空替换为 0000

mysql - 在庞大的数据集上使用 IN 是个好主意吗?

mysql - 如何在mysql的同一个表中选择更新?

php - 根据变量($_POST)是否存在创建sql查询

database - 查询高基数字段

php - 如何使用 2 个表格正确显示带有评论的项目

mysql - 将 # 个结果合并在一起

php - 师生数据库设计