简体   繁体   English

如何在mysql上优化此sql查询

[英]how to optimize this sql query on mysql

SELECT Matricule, Nom, Section, Nom_Section,
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pb1, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pt1, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv1, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-21' and '2016-2-20') and (t.Matricule=p.Matricule))) as pb2, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-21' and '2016-2-20') and (t.Matricule=p.Matricule))) as pt2, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-21' and '2016-2-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv2, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-2-21' and '2016-3-20') and (t.Matricule=p.Matricule))) as pb3, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-2-21' and '2016-3-20') and (t.Matricule=p.Matricule))) as pt3, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-2-21' and '2016-3-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv3, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-3-21' and '2016-4-20') and (t.Matricule=p.Matricule))) as pb4, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-3-21' and '2016-4-20') and (t.Matricule=p.Matricule))) as pt4, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-3-21' and '2016-4-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv4, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-4-21' and '2016-5-20') and (t.Matricule=p.Matricule))) as pb5, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-4-21' and '2016-5-20') and (t.Matricule=p.Matricule))) as pt5, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-4-21' and '2016-5-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv5, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-5-21' and '2016-6-20') and (t.Matricule=p.Matricule))) as pb6, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-5-21' and '2016-6-20') and (t.Matricule=p.Matricule))) as pt6, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-5-21' and '2016-6-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv6, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-6-21' and '2016-7-20') and (t.Matricule=p.Matricule))) as pb7, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-6-21' and '2016-7-20') and (t.Matricule=p.Matricule))) as pt7, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-6-21' and '2016-7-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv7, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-7-21' and '2016-8-20') and (t.Matricule=p.Matricule))) as pb8, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-7-21' and '2016-8-20') and (t.Matricule=p.Matricule))) as pt8, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-7-21' and '2016-8-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv8, 
 (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pb9, 
(select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pt9, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-5-21' and '2016-6-3') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv9, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pb10, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pt10, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv10, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pb11, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pt11, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv11, 
         (select sum(Presence_Badge_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pb12, 
         (select sum(Presence_theorique_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (t.Matricule=p.Matricule))) as pt12, 
         (select sum(Valeur_minutes) from presence t where ((Date_Effet BETWEEN '2016-1-1' and '2016-1-20') and (Motif in ('ABSI','CP','CMAR','CMAT','CNAI','COCH','FERI','FINP','DEPL','CODC','DELE','FORM','HSUP','MALA','VMED','ALET','RECU','ACTBAD'))and (t.Matricule=p.Matricule))) as pv12 
         from Presence p  group by Matricule;

i have attached picture of explain query and this is my table enter image description here 我已附上解释查询的图片,这是我的表格, 在此处输入图片说明

CREATE TABLE `presence` ( `id` int(10) NOT NULL AUTO_INCREMENT,
`date_effet` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`matricule` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
 `motif` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
 `nom` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
 `nom_section` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT
NULL,
 `presence_badge` tinyblob,
 `presence_badge_minutes` int(10) NOT NULL,
 `presence_theorique` tinyblob,
 `presence_theorique_minutes` int(10) NOT NULL,
 `section` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
 `valeur` tinyblob,
 `valeur_minutes` int(10) NOT NULL,
 PRIMARY KEY (`id`,`date_effet`),
 KEY `matricule_index` (`matricule`),
 KEY `pres_index` (`matricule`,`nom`,`section`,`nom_section`)
) ENGINE=InnoDB AUTO_INCREMENT=673810 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (TO_DAYS(date_effet))
(PARTITION p_jan VALUES LESS THAN (736349) ENGINE = InnoDB,
PARTITION p_fev VALUES LESS THAN (736380) ENGINE = InnoDB,
PARTITION p_mar VALUES LESS THAN (736409) ENGINE = InnoDB,
PARTITION p_avr VALUES LESS THAN (736440) ENGINE = InnoDB,
PARTITION p_mai VALUES LESS THAN (736470) ENGINE = InnoDB,
PARTITION p_jui VALUES LESS THAN (736501) ENGINE = InnoDB,
PARTITION p_juil VALUES LESS THAN (736531) ENGINE = InnoDB,
PARTITION p_aou VALUES LESS THAN (736562) ENGINE = InnoDB,
PARTITION p_sep VALUES LESS THAN (736593) ENGINE = InnoDB,
PARTITION p_oct VALUES LESS THAN (736623) ENGINE = InnoDB,
PARTITION p_nov VALUES LESS THAN (736654) ENGINE = InnoDB,
PARTITION p_dec VALUES LESS THAN (736684) ENGINE = InnoDB) */

i did create a partition range on columns 'date_effet' and two index one on matricule and the other one is couvering index on (matricule,Nom,Section,Nom_section) 我确实在列'date_effet'上创建了一个分区范围,在矩阵上创建了两个索引,另一个在(matricule,Nom,Section,Nom_section)上建立了索引

First I'd add Date_Effet to the actual index. 首先,我将Date_Effet添加到实际索引中。 (First field in the index due you're really filtering by date, and grouping by Matricule, Nom, Section, Nom Section .) (由于实际上要按日期过滤,并按Matricule, Nom, Section, Nom Section分组,因此索引中的第一个字段。)

Then I would change subqueries by SUM(CASE( and add a WHERE clause that covers all data range. 然后,我将通过SUM(CASE(更改子查询,并添加一个覆盖所有数据范围的WHERE子句。

select
    Matricule, Nom, Section, Nom Section,
    sum(case Presence_theorique_minutes when (Date_Effet BETWEEN '2016-1-1' and '2016-1-20') then Presence_theorique_minutes else 0 end) as PTM01,
    sum(case Presence_theorique_minutes when (Date_Effet BETWEEN '2016-1-21' and '2016-2-20') then Presence_theorique_minutes else 0 end) as PTM02,
    ...
    sum(case Valeur_minutes when (Date_Effet BETWEEN '2016-1-1' and '2016-1-20') then Valeur_minutes else 0 end) as VM01,
    sum(case Valeur_minutes when (Date_Effet BETWEEN '2016-1-21' and '2016-2-20') then Valeur_minutes else 0 end) as VM02,
    ...
    sum(case Presence_Badge_minutes when (Date_Effet BETWEEN '2016-1-1' and '2016-1-20') then Presence_Badge_minutes else 0 end) as PBM01,
    sum(case Presence_Badge_minutes when (Date_Effet BETWEEN '2016-1-21' and '2016-2-20') then Presence_Badge_minutes else 0 end) as PBM02,
from 
    Presence use index(Date_Effet, Matricule, Nom, Section, Nom Section)
where 
    Date_Effet BETWEEN 'MIN_DATE' and 'MAX_DATE'
group by 
    Matricule, Nom, Section, Nom Section;

In this case and due to the date range (20 to 20), I'd add a new field to the table. 在这种情况下,由于日期范围(20到20),我将在表中添加一个新字段。 Something similar to analysis_period . 类似于analysis_period Build this field as: [YEAR+TEORIC MONTH] 将此字段构建为:[YEAR + TEORIC MONTH]

+------------+-----------------+
|    date    | analysis_period |
+------------+-----------------+
| 2016-01-11 |      201601     |
+------------+-----------------+
| 2016-01-21 |      201602     |
+------------+-----------------+
| 2016-02-01 |      201602     |
+------------+-----------------+
| 2016-02-25 |      201603     |
+------------+-----------------+

Then you can easily group by this field using a single SELECT . 然后,您可以使用单个SELECT轻松按此字段分组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM