【问题标题】:MySQL Getting a count on two parametersMySQL 计算两个参数
【发布时间】:2011-02-07 20:22:26
【问题描述】:

我有一个订单表,其中包含超过 2 亿条记录。对于统计数据,我需要获得三个不同的计数。首先是某个日期范围内的订单数量,然后是特定状态下的订单数量,最后是特定日期范围内特定状态的订单数量。前两个查询平均返回 10-2000 万条记录,通常需要不到 5 秒的时间。但是,我无法在一个小时内获得第三个查询以返回结果。以下是实际查询:

SELECT COUNT(*) 
  FROM orders 
 WHERE order_date BETWEEN date1 AND date2; 

上面有1000万条记录要汇总,查询需要4秒。

   SELECT COUNT(*) 
     FROM orders 
LEFT JOIN customers ON orders.customer_id = customers.customer_id 
    WHERE customer.state = 'PA'; 

上面有1500万条记录要汇总,查询需要5秒。

(SELECT COUNT(*) 
   FROM orders 
  WHERE order_date BETWEEN date1 AND date2) 
UNION 
(SELECT COUNT(*) 
   FROM orders 
LEFT JOIN customers ON orders.customer_id=customers.customer_id
    WHERE customer.state = 'PA'); 

上面有4500条记录要汇总,查询需要2个小时。

对于第三个查询,我可以采取另一种方法来在更合理的时间内为我提供计数吗?最好不到一分钟?

【问题讨论】:

  • 您能否发布表格定义以及 EXPLAIN 输出?
  • 您意识到 UNION 将删除重复项 - 如果两者都是 25,您将只看到一行。
  • 忘记时间,第三次查询没有返回正确的结果。
  • “返回 10-2000 万条记录”是指搜索 1000 万条记录。没有GROUP BYCOUNT(*) 只会返回 1 条记录。
  • 我的意思是返回的计数在 10000000 和 20000000 之间。我的理论是第三个操作必须比较这么多数据是它花费这么长时间的原因。

标签: sql mysql


【解决方案1】:

将查询连接在一起。另外,将LEFT JOIN 更改为INNER JOIN,因为您是按客户状态进行过滤的。

SELECT COUNT(*) 
FROM orders 
    INNER JOIN customers ON orders.customer_id=customers.customer_id
WHERE customer.state = 'PA' AND order_date BETWEEN date1 AND date2

【讨论】:

    【解决方案2】:

    您的 3 个查询应该是。

    SELECT COUNT(*) 
      FROM orders 
     WHERE order_date BETWEEN date1 AND date2; 
    
    SELECT COUNT(*) 
          FROM orders 
    INNER JOIN customers ON orders.customer_id = customers.customer_id 
         WHERE customer.state = 'PA'; 
    
    SELECT COUNT(*) 
          FROM orders 
    INNER JOIN customers ON orders.customer_id = customers.customer_id 
         WHERE customer.state = 'PA'
           AND order_date BETWEEN date1 AND date2;
    

    第二个可以是 LEFT JOIN,但由于您使用 WHERE 子句过滤客户,因此没有理由保留任何来自 LEFT JOIN 的记录。

    对于它的价值,您尝试在单个查询中从查询 1 和 2 返回计数的第三个查询工作缓慢most likely,因为 MySQL 看着 UNION 并且一切都很有趣。以下任何一个都应该更好地工作

    SELECT "Date", COUNT(*) 
       FROM orders 
      WHERE order_date BETWEEN date1 AND date2
    UNION ALL
    SELECT "Customer", COUNT(*) 
       FROM orders 
    LEFT JOIN customers ON orders.customer_id=customers.customer_id
        WHERE customer.state = 'PA';
    

    SELECT
    (SELECT COUNT(*) 
       FROM orders 
      WHERE order_date BETWEEN date1 AND date2) DateCount,
    (SELECT COUNT(*) 
       FROM orders 
    LEFT JOIN customers ON orders.customer_id=customers.customer_id
        WHERE customer.state = 'PA') CustomerCount
    

    (第二个将其返回为两列而不是两行)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 2012-07-11
      相关资源
      最近更新 更多