Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.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 前20名组排名查询-优化_Mysql_Optimization - Fatal编程技术网

Mysql 前20名组排名查询-优化

Mysql 前20名组排名查询-优化,mysql,optimization,Mysql,Optimization,我正在创建一个报告结构,在这个结构中,我需要为每个独特的公司-地区输出前20天的汇总统计数据。我已经完成了这个任务,但觉得我的代码过于复杂,我请求帮助优化它 在这个过程中,我有两个表。第一个列表列出了所有可能的公司-地区-集团-子集团。第二个按组-子组列出每小时统计数据 SQL Fiddle链接: 注意:当前在我的SQL FIDLE上获得一个SELECT命令拒绝给用户@for table'table_stats'错误,也希望能帮助解决这个问题 表4公司声明和虚拟数据: 表2: 简化为每天只包含一

我正在创建一个报告结构,在这个结构中,我需要为每个独特的公司-地区输出前20天的汇总统计数据。我已经完成了这个任务,但觉得我的代码过于复杂,我请求帮助优化它

在这个过程中,我有两个表。第一个列表列出了所有可能的公司-地区-集团-子集团。第二个按组-子组列出每小时统计数据

SQL Fiddle链接: 注意:当前在我的SQL FIDLE上获得一个SELECT命令拒绝给用户@for table'table_stats'错误,也希望能帮助解决这个问题

表4公司声明和虚拟数据:

表2: 简化为每天只包含一个小组的几个小时

要优化的查询:


tl;博士:很抱歉发了这么长的帖子。请求优化。

只需为组包含一个索引,这样连接就会更有效

CREATE TABLE table_companies
    (`pk_id` int, `company` varchar(8), 
     `region` varchar(8), `group` varchar(7), `subgroup` varchar(10),
     PRIMARY KEY (`pk_id`),
     UNIQUE KEY `pk_id_id_UNIQUE` (`pk_id`),  

     INDEX idx_group (`group`, `subgroup`)
    )
;

我所做的修改:

完全修改了您的查询 在组、子组的表_companies表中添加了复合索引 在组、子组的表_stats表中添加了复合索引 修改的查询:

结果集中没有秩列。因为结果是按照排名降序排序的,所以您可以隐式地将结果集中的行位置视为排名。然而,如果您真的需要排名列,那么这里有一个

综合指数公司:

复合可索引统计信息:

解释结果:

好消息是MySQL可以使用这些索引,因为它们在可能的键下。尽管它显示的都是表格公司的类型。我所能说的只是一小部分数据。您不能根据一小部分数据来判断性能

更多:

我猜这些表中有主键。如果没有,那么创建

编辑:


错误是因为您试图使用schema1.tablename是否创建了索引?您是否考虑过为这些索引创建表,并将主表中的引用作为这些表中的ID,而不是为公司/地区/集团/子集团使用字符串?比较整数和ID要比字符串快得多。而且它的结构更好,你可以在主表中有其他你不想每次重复的公司信息。主键是唯一的键,所以不要做冗余索引。查询有点混乱。概述了您需要的代码。这与我最初尝试的一次迭代类似,但由于限制20只会为所有可能的公司-地区-集团-子集团提供前20名,因此决定放弃此方法。我要求每个单独的业务部门排名前20位。我很抱歉,因为我的数据表明这是一个可行的解决方案,但出于演示目的,我只包括了1个单元。总结果应为业务单位数量乘以20。期待您可能找到的任何其他解决方案。您如何识别每个独立的业务部门?您是否希望每个业务部门获得前20名的结果@nbayly请澄清哪些字段一起唯一标识业务单位。如果有5个唯一的业务单元,那么结果集中最多有5*20=100行。是吗?每个业务单元都是每个独特的公司-地区-集团-子集团,是的,我要求每个业务单元的前20名结果。对于我提供的样本表_companies,需要返回16个业务单元*20=320行。由于业务单元=公司-地区-集团-子集团的唯一组合,因此您应该按公司-地区-集团-子集团进行分组。但在查询中,您只使用了company and RegionTank作为回答。问题再次围绕着代码的简化/简化。性能不是一个问题,因为数据集不大,而且它是一个临时过程,而不是操作过程。问题是我必须不断地向这个查询中添加计算,我关心的是可读性和过于复杂。
CREATE TABLE `table_stats` (
  `pk_id` int(10) unsigned NOT NULL,
  `date_time` datetime NOT NULL,
  `group` varchar(45) NOT NULL,
  `subgroup` varchar(45) NOT NULL,
  `stat` int(10) unsigned NOT NULL,
  PRIMARY KEY (`pk_id`),
  UNIQUE KEY `pk_id_UNIQUE` (`pk_id`),
  UNIQUE KEY `om_unique` (`date_time`,`group`,`subgroup`)
);

INSERT INTO table_stats
    (`pk_id`, `date_time`, `group`, `subgroup`, `stat`)
VALUES
    (1, '2015-12-01 06:00:00', 'group9', 'subgroup10', 14),
    (2, '2015-12-01 12:00:00', 'group9', 'subgroup10', 14),
    (3, '2015-12-02 06:00:00', 'group9', 'subgroup10', 2),
    (4, '2015-12-02 12:00:00', 'group9', 'subgroup10', 51),
    (5, '2015-12-03 06:00:00', 'group9', 'subgroup10', 30),
    (6, '2015-12-03 12:00:00', 'group9', 'subgroup10', 6),
    (7, '2015-12-04 06:00:00', 'group9', 'subgroup10', 9),
    (8, '2015-12-04 12:00:00', 'group9', 'subgroup10', 77),
    (9, '2015-12-05 06:00:00', 'group9', 'subgroup10', 70),
    (10, '2015-12-05 12:00:00', 'group9', 'subgroup10', 7),
    (11, '2015-12-06 06:00:00', 'group9', 'subgroup10', 38),
    (12, '2015-12-06 12:00:00', 'group9', 'subgroup10', 5),
    (13, '2015-12-07 06:00:00', 'group9', 'subgroup10', 86),
    (14, '2015-12-07 12:00:00', 'group9', 'subgroup10', 73),
    (15, '2015-12-08 06:00:00', 'group9', 'subgroup10', 45),
    (16, '2015-12-08 12:00:00', 'group9', 'subgroup10', 14),
    (17, '2015-12-09 06:00:00', 'group9', 'subgroup10', 66),
    (18, '2015-12-09 12:00:00', 'group9', 'subgroup10', 38),
    (19, '2015-12-10 06:00:00', 'group9', 'subgroup10', 12),
    (20, '2015-12-10 12:00:00', 'group9', 'subgroup10', 77),
    (21, '2015-12-11 06:00:00', 'group9', 'subgroup10', 21),
    (22, '2015-12-11 12:00:00', 'group9', 'subgroup10', 18),
    (23, '2015-12-12 06:00:00', 'group9', 'subgroup10', 28),
    (24, '2015-12-12 12:00:00', 'group9', 'subgroup10', 74),
    (25, '2015-12-13 06:00:00', 'group9', 'subgroup10', 20),
    (26, '2015-12-13 12:00:00', 'group9', 'subgroup10', 37),
    (27, '2015-12-14 06:00:00', 'group9', 'subgroup10', 66),
    (28, '2015-12-14 12:00:00', 'group9', 'subgroup10', 59),
    (29, '2015-12-15 06:00:00', 'group9', 'subgroup10', 26),
    (30, '2015-12-15 12:00:00', 'group9', 'subgroup10', 0),
    (31, '2015-12-16 06:00:00', 'group9', 'subgroup10', 77),
    (32, '2015-12-16 12:00:00', 'group9', 'subgroup10', 31),
    (33, '2015-12-17 06:00:00', 'group9', 'subgroup10', 59),
    (34, '2015-12-17 12:00:00', 'group9', 'subgroup10', 71),
    (35, '2015-12-18 06:00:00', 'group9', 'subgroup10', 7),
    (36, '2015-12-18 12:00:00', 'group9', 'subgroup10', 73),
    (37, '2015-12-19 06:00:00', 'group9', 'subgroup10', 72),
    (38, '2015-12-19 12:00:00', 'group9', 'subgroup10', 28),
    (39, '2015-12-20 06:00:00', 'group9', 'subgroup10', 50),
    (40, '2015-12-20 12:00:00', 'group9', 'subgroup10', 11),
    (41, '2015-12-21 06:00:00', 'group9', 'subgroup10', 71),
    (42, '2015-12-21 12:00:00', 'group9', 'subgroup10', 4),
    (43, '2015-12-22 06:00:00', 'group9', 'subgroup10', 78),
    (44, '2015-12-22 12:00:00', 'group9', 'subgroup10', 69),
    (45, '2015-12-23 06:00:00', 'group9', 'subgroup10', 83),
    (46, '2015-12-23 12:00:00', 'group9', 'subgroup10', 55),
    (47, '2015-12-24 06:00:00', 'group9', 'subgroup10', 71),
    (48, '2015-12-24 12:00:00', 'group9', 'subgroup10', 20),
    (49, '2015-12-25 06:00:00', 'group9', 'subgroup10', 90),
    (50, '2015-12-25 12:00:00', 'group9', 'subgroup10', 26),
    (51, '2015-12-26 06:00:00', 'group9', 'subgroup10', 1),
    (52, '2015-12-26 12:00:00', 'group9', 'subgroup10', 73),
    (53, '2015-12-27 06:00:00', 'group9', 'subgroup10', 4),
    (54, '2015-12-27 12:00:00', 'group9', 'subgroup10', 18),
    (55, '2015-12-28 06:00:00', 'group9', 'subgroup10', 4),
    (56, '2015-12-28 12:00:00', 'group9', 'subgroup10', 30),
    (57, '2015-12-29 06:00:00', 'group9', 'subgroup10', 56),
    (58, '2015-12-29 12:00:00', 'group9', 'subgroup10', 53),
    (59, '2015-12-30 06:00:00', 'group9', 'subgroup10', 33),
    (60, '2015-12-31 12:00:00', 'group9', 'subgroup10', 8)
;
SELECT * FROM
    (
    SELECT t3.company,t3.region,t3.day, t3.day_stat,COUNT(*) as rank
    FROM
        (
            SELECT t2.company,t2.region,DAY(t1.date_time) as day,SUM(t1.stat) as day_stat
            FROM schema1.table_stats t1
            INNER JOIN table_companies t2
            ON t1.group=t2.group AND t1.subgroup=t2.subgroup
            WHERE
                MONTH(t1.date_time)=12 AND
                YEAR(t1.date_time)=2015
            group by t2.company,t2.region,DAY(t1.date_time)
            ORDER BY t2.company,t2.region,day_stat DESC
        ) t3
    JOIN
    (
            SELECT t2.company,t2.region,DAY(t1.date_time) as day,SUM(t1.stat) as day_stat
            FROM schema1.table_stats t1
            INNER JOIN table_companies t2
            ON t1.group=t2.group AND t1.subgroup=t2.subgroup
            WHERE
                MONTH(t1.date_time)=12 AND
                YEAR(t1.date_time)=2015
            group by t2.company,t2.region,DAY(t1.date_time)
            ORDER BY t2.company,t2.region,day_stat DESC
        ) t4
    ON
        t4.day_stat >= t3.day_stat AND
        t4.company = t3.company AND
        t4.region = t3.region
    GROUP BY t3.company,t3.region,t3.day_stat
    ORDER BY t3.company,t3.region,rank
    ) t5
WHERE t5.rank<=20
;
INSERT INTO results
    (`company`, `region`, `day`, `day_stat`, `rank`)
VALUES
    ('company3', 'region6', 7, 159, 1),
    ('company3', 'region6', 22, 147, 2),
    ('company3', 'region6', 23, 138, 3),
    ('company3', 'region6', 17, 130, 4),
    ('company3', 'region6', 14, 125, 5),
    ('company3', 'region6', 25, 116, 6),
    ('company3', 'region6', 29, 109, 7),
    ('company3', 'region6', 16, 108, 8),
    ('company3', 'region6', 9, 104, 9),
    ('company3', 'region6', 12, 102, 10),
    ('company3', 'region6', 19, 100, 11),
    ('company3', 'region6', 24, 91, 12),
    ('company3', 'region6', 10, 89, 13),
    ('company3', 'region6', 4, 86, 14),
    ('company3', 'region6', 18, 80, 15),
    ('company3', 'region6', 5, 77, 16),
    ('company3', 'region6', 21, 75, 17),
    ('company3', 'region6', 26, 74, 18),
    ('company3', 'region6', 20, 61, 19),
    ('company3', 'region6', 8, 59, 20)
;
CREATE TABLE table_companies
    (`pk_id` int, `company` varchar(8), 
     `region` varchar(8), `group` varchar(7), `subgroup` varchar(10),
     PRIMARY KEY (`pk_id`),
     UNIQUE KEY `pk_id_id_UNIQUE` (`pk_id`),  

     INDEX idx_group (`group`, `subgroup`)
    )
;
SELECT 
    C.company,
    C.region,
    DAY(S.date_time) day,
    SUM(S.stat) day_stat
FROM table_companies C
INNER JOIN table_stats S
ON C.`group` = S.`group` AND C.subgroup = S.subgroup
WHERE MONTH(S.date_time) = 12 AND YEAR(S.date_time) = 2015
GROUP BY C.company, C.region, DAY(S.date_time)
ORDER BY day_stat DESC
LIMIT 20;
ALTER TABLE `table_companies` ADD INDEX `idx_table_compnaies_group_subgroup` (
    `group`,
    `subgroup`
);
ALTER TABLE `table_stats` ADD INDEX `idx_table_stats_group_subgroup` (
`group`,
`subgroup`
);
id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  S   ALL idx_table_compnaies_group_subgroup              60  Using where; Using temporary; Using filesort
1   SIMPLE  C   ref idx_table_companies_group_subgroup  idx_table_companies_group_subgroup  57  schema1.S.group,schema1.S.subgroup  1   Using index condition
SELECT 
    C.company,
    C.region,
    tt.day,
    tt.total AS day_stat,
    tt.rank
FROM table_companies C 
INNER JOIN 
(
SELECT 
t.*,
IF(t.businessUnit = @sameBusinessUnit, @rn := @rn + 1, @rn := 1) AS rank,
@sameBusinessUnit := t.businessUnit
FROM 
(
    SELECT 
       S1.`group`,
       S1.subgroup,
       CONCAT(S1.`group`,S1.subgroup) AS businessUnit,
       DAY(S1.date_time) AS day,
       SUM(S1.stat) total
    FROM table_stats S1
    GROUP BY S1.group,S1.subgroup,DAY(S1.date_time)
    ORDER BY total DESC
)AS t
CROSS JOIN (SELECT @rn := 1, @sameBusinessUnit := '') var
) AS tt
ON C.`group`=tt.`group` AND C.subgroup = tt.subgroup
WHERE tt.rank <= 20
ORDER BY tt.`group`,tt.`subgroup`,tt.rank;