mysql - 使用 GROUP BY 优化 SQL 查询

标签 mysql sql

我需要帮助解决使用 group by 时查询运行缓慢的问题:

SELECT           `customers`.`id` 
                ,`customers`.`firstname`
                ,`customers`.`lastname`
                ,`customers`.`address`
                ,`customers`.`address_co`
                ,`customers`.`country`
                ,`customers`.`zipcode`
                ,`customers`.`city`
                ,`customers`.`phone`
                ,`customers`.`mobilephone`
                ,`customers`.`ssn`
                ,`users`.`email`
                ,`customer_lists`.`name`        AS `customerList`
                ,COUNT( transactions.id )       AS transactions_count
                ,SUM( transactions.sum_incl )   AS sum_incl
                ,SUM( transactions.sum_excl )   AS sum_excl
                ,`customers`.`created_at` 
FROM            `customers` 
INNER JOIN      `users` 
ON              `customers`.`user_id` = `users`.`id` 
LEFT JOIN       `transactions` 
ON              `customers`.`id` = `transactions`.`customer_id` 
INNER JOIN      `customer_lists`
ON              `customers`.`customer_list_id` = `customer_lists`.`id` 
WHERE           `customer_lists`.`club_id` =  '1'
GROUP BY        `customers`.`id` 
ORDER BY        `customers`.`created_at` DESC 

当我运行 EXPLAIN 时,它说 Using temporary;使用文件排序

**id**  **select_type** **table**       **type**    **possible_keys**                                       **key**                             **key_len** **ref**                             **rows**    **Extra**
1       SIMPLE          customer_lists  ref         PRIMARY,club_id_index                                   club_id_index                       8           const                               1           Using temporary; Using filesort
1       SIMPLE          customers       ref         customers_user_id_foreign,customers_customer_list_...   customers_customer_list_id_index    8           kund_workbox_nu.customer_lists.id   867  
1       SIMPLE          users           eq_ref      PRIMARY                                                 PRIMARY                             8           kund_workbox_nu.customers.user_id   1    
1       SIMPLE          transactions    ref         customer_id_index                                       customer_id_index                   8           kund_workbox_nu.customers.id        3108

 

我该如何解决?

更新

表:

客户

CREATE TABLE `customers` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL,
  `customer_list_id` bigint(20) unsigned NOT NULL,
  `firstname` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `lastname` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `address` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `address_co` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `country` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `zipcode` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `city` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `phone` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `mobilephone` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `ssn` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
  `last_login` datetime NOT NULL,
  `added_information` tinyint(1) NOT NULL DEFAULT '0',
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `customers_user_id_foreign` (`user_id`),
  KEY `customers_customer_list_id_index` (`customer_list_id`),
  CONSTRAINT `customers_customer_list_id_foreign` FOREIGN KEY (`customer_list_id`) REFERENCES `customer_lists` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `customers_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=29739 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

交易

CREATE TABLE `transactions` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `transaction_type_id` bigint(20) unsigned NOT NULL,
  `customer_id` bigint(20) unsigned NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `sum_incl` decimal(15,4) NOT NULL,
  `sum_excl` decimal(15,4) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `transactions_customer_id_foreign` (`customer_id`),
  KEY `transactions_transaction_type_id_foreign` (`transaction_type_id`),
  CONSTRAINT `transactions_customer_id_foreign` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `transactions_transaction_type_id_foreign` FOREIGN KEY (`transaction_type_id`) REFERENCES `transaction_types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=580116 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

客户名单

CREATE TABLE `customer_lists` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `club_id` bigint(20) unsigned NOT NULL,
  `name` varchar(90) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `customer_lists_club_id_foreign` (`club_id`),
  CONSTRAINT `customer_lists_club_id_foreign` FOREIGN KEY (`club_id`) REFERENCES `clubs` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

最佳答案

或许尝试将单个表作为派生表对事务进行分组?

SELECT
      `customers`.`id`
    , `customers`.`firstname`
    , `customers`.`lastname`
    , `customers`.`address`
    , `customers`.`address_co`
    , `customers`.`country`
    , `customers`.`zipcode`
    , `customers`.`city`
    , `customers`.`phone`
    , `customers`.`mobilephone`
    , `customers`.`ssn`
    , `users`.`email`
    , `customer_lists`.`name` AS `customerList`
    , `trans`.transactions_count
    , `trans`.sum_incl
    , `trans`.sum_excl
    , `customers`.`created_at`
FROM `customers`
INNER JOIN `users` ON `customers`.`user_id` = `users`.`id`
INNER JOIN `customer_lists` ON `customers`.`customer_list_id` = `customer_lists`.`id`
LEFT JOIN (
    SELECT
          `transactions`.`customer_id`
        , COUNT(transactions.id) AS transactions_count
        , SUM(transactions.sum_incl) AS sum_incl
        , SUM(transactions.sum_excl) AS sum_excl
    FROM `transactions`
    GROUP BY `transactions`.`customer_id`
    ) `trans` ON `customers`.`id` = `trans`.`customer_id`
WHERE `customer_lists`.`club_id` = '1'
ORDER BY `customers`.`created_at` DESC

该子查询中的 where 子句也可能有所帮助。

关于mysql - 使用 GROUP BY 优化 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26174442/

相关文章:

sql - Go:用sql删除帖子

php - 即使存在两个条目,数据库查询也返回 0 行

c# - 带有 Group By 和带有 Min(string) 的 Having 子句的 LINQ

mysql - 多列求和并更新总计字段[MySQL]

PHP - MySQL 查询拒绝执行

mysql - SQL - 错误代码 1005,错误编号 121

sql - 展平枚举表中的 T-SQL 位掩码

php - 编辑 php 中数据库的选项值

mysql - 与包共享数据库连接

mysql - 如何在MySql中获取值的总和