如何在MYSQL选择查询中进行多次计数?

时间:2017-11-10 20:23:20

标签: mysql query-optimization

SELECT count(item_id) as today FROM table1 
WHERE DATE(creation_date) > DATE(NOW() - INTERVAL 1 DAY);

SELECT count(item_id) as yesterday from table1
where DATE(creation_date) = DATE(NOW() - INTERVAL 1 DAY);

SELECT count(item_id) year_period from table1
where creation_date > now() - interval 1 year;

我有以下查询,我想从这些查询中返回一行返回的结果。 如下图所示:

----------------------------------------
|today |  yesterday  | one_year_period |
----------------------------------------
|   2  |    5        |        7        |
----------------------------------------

我获得了一些赞美这一点的方法,但我想要一个更有效的解决方案来实现我想要的。 我可以通过使用这里看到的联盟来完成我想要的东西

SELECT count(item_id) as today FROM table1 
WHERE DATE(creation_date) > DATE(NOW() - INTERVAL 1 DAY)
union
SELECT count(item_id) as yesterday from table1
where DATE(creation_date) = DATE(NOW() - INTERVAL 1 DAY)
union
SELECT count(item_id) year_period from table1
where creation_date > now() - interval 1 year;

我想优化我的解决方案,以便不会在3个单独的场合重复查询。

3 个答案:

答案 0 :(得分:1)

使用CASE语句:

SELECT 
    SUM(CASE WHEN DATE(creation_date) > DATE(NOW() - INTERVAL 1 DAY) THEN 1 END) as today,
    SUM(CASE WHEN DATE(creation_date) = DATE(NOW() - INTERVAL 1 DAY) THEN 1 END) AS yesterday,
    SUM(CASE WHEN creation_date > now() - interval 1 year THEN 1 END) AS year_period
FROM table1 

答案 1 :(得分:0)

SELECT 
   SUM(CASE WHEN DATE(creation_date) > DATE(NOW() - INTERVAL 1 DAY) THEN 1 ELSE 0 END) today,
   SUM(CASE WHEN DATE(creation_date) = DATE(NOW() - INTERVAL 1 DAY) THEN 1 ELSE 0 END) yesterday,
   SUM(CASE WHEN date(creation_date) > now() - interval 1 year THEN 1 ELSE 0 END) last_year
FROM table1

答案 2 :(得分:0)

如果您正在寻找效率,请执行此操作,以避免说出DATE(creation_date),并使用COUNT(*)代替COUNT(column)。这样,您就可以在creation_date列上使用索引。

 SELECT count(*) as today 
   FROM table1 
  WHERE creation_date >= CURDATE()

而且,如果您拥有该索引并使用我展示的那种模式,那么像您原始查询的内容远比一堆SUM(CASE...))条款快 。为什么?因为MySQL可以通过执行所谓的loose index scans. Loose index scans are astonishingly fast来满足查询。

SELECT count(*) as today FROM table1 
WHERE creation_date >= CURDATE()
union
SELECT count(*) as yesterday
 from table1
where creation_date >= CURDATE() - INTERVAL 1 DAY
  and creation_date <  CURDATE()
union
SELECT count(*) year_period from table1
where creation_date >= CURDATE() - interval 1 year;