使用group_concat优化MySQL查询

问题描述 投票:0回答:1

我有一个旧的 PHP5 MySQL Web 应用程序,其代码必须适应 PHP8/MySQL14.14

有一个视图,查询几个表并基于该代码:

(SELECT `db_demandes`.`bdd`.`id`
        AS `Id`,
        `db_demandes`.`bdd`.`ref`
        AS `Ref`,
        `db_demandes`.`bdd`.`nodossier`
        AS `NoDossier`,
        `db_demandes`.`bdd`.`agentfirme`
        AS `Agentfirme`,
        `db_demandes`.`bdd`.`agentanterieur`
        AS `AgentAnterieur`,
        Concat(`db_demandes`.`bdd`.`nom`, '\r\n', `db_demandes`.`bdd`.`prenom`)
        AS
`Demandeur`,
Concat(`db_demandes`.`bdd`.`no_o`, ' ', `db_demandes`.`bdd`.`rue_o`, '\r\n', `db_demandes`.`bdd`.`cp_o`, ' ', `db_demandes`.`bdd`.`localite_o`)
        AS `Adresse`,
`db_demandes`.`bdd`.`protection`
        AS `Protection`,
`db_demandes`.`bdd`.`type_objet`
        AS `Type_Objet`,
`db_demandes`.`bdd`.`datation_o`
        AS `Datation_O`,
`db_demandes`.`bdd`.`datedemandesubsideavt`
        AS `DateDemandeSubsideAVT`,
REPLACE(`db_demandes`.`bdd`.`datef1`, '+', '\n')
        AS `DateF1`,
REPLACE(`db_demandes`.`bdd`.`datear1`, '+', '\n')
        AS `DateAR1`,
`db_demandes`.`bdd`.`datedemandeavise`
        AS `DateDemandeAvise`,
`db_demandes`.`bdd`.`dateavisfirme_e`
        AS `DateAvisfirme_E`,
`db_demandes`.`bdd`.`dateavisfirme_o`
        AS `DateAvisfirme_O`,
`db_demandes`.`bdd`.`dtdatedemandeauthtrav`
        AS `dtDateDemandeAuthTrav`,
`db_demandes`.`bdd`.`dtdatedecisionDirection`
        AS `dtDateDecisionDirection`,
Group_concat(DISTINCT `avantpromesse`.`dtdate` SEPARATOR ' ')
        AS `V1`,
`db_demandes`.`bdd`.`daterefusavt`
        AS `DateRefusAVT`,
`db_demandes`.`bdd`.`email`
        AS `Email`,
`db_demandes`.`bdd`.`travaux_a_subventionner`
        AS `Travaux_a_subventionner`,
`db_demandes`.`bdd`.`pc`
        AS `PC`,
`db_demandes`.`bdd`.`ff`
        AS `FF`,
(SELECT Group_concat(`db_demandes`.`tblpromesses`.`montantestimatifpromesse`
        SEPARATOR
        ' ')
 FROM   `db_demandes`.`tblpromesses`
 WHERE  ( `db_demandes`.`tblpromesses`.`fidossier` = `db_demandes`.`bdd`.`ref` )
 ORDER  BY `db_demandes`.`tblpromesses`.`idpromesse`)
        AS `MontantsEstimatifs`,
(SELECT Group_concat(`db_demandes`.`tblpromesses`.`dtdatepromesse` SEPARATOR ' '
        )
 FROM   `db_demandes`.`tblpromesses`
 WHERE  ( `db_demandes`.`tblpromesses`.`fidossier` = `db_demandes`.`bdd`.`ref` )
 ORDER  BY `db_demandes`.`tblpromesses`.`idpromesse`)
        AS `DatesPromesses`,
Group_concat(DISTINCT `db_demandes`.`tblvisites`.`dtdate` SEPARATOR ' ')
        AS
`Visites`,
`db_demandes`.`tblsuivi`.`dtavancementtravaux`
        AS
     `dtAvancementTravaux`,
Trim(Concat(`db_demandes`.`tblsuivi`.`dtobservations`, '\r\n', REPLACE(
          `db_demandes`.`tblsuivi`.`dtavancementtravaux`, '\r\n', 'X')))
        AS
`dtObservations`,
`db_demandes`.`tblsuivi`.`dtetat`
        AS `dtEtat`,
`db_demandes`.`bdd`.`paiementsprevisionnels2011`
        AS `PaiementsPrevisionnels2011`,
`db_demandes`.`bdd`.`paiementsprevisionnels2012`
        AS `PaiementsPrevisionnels2012`,
REPLACE(`db_demandes`.`bdd`.`datef2`, '+', '\n')
        AS `DateF2`,
REPLACE(`db_demandes`.`bdd`.`datear2`, '+', '\n')
        AS `DateAR2`,
`db_demandes`.`bdd`.`daterefusap_t`
        AS `DateRefusAP_T`,
`db_demandes`.`bdd`.`tt`
        AS `TT`,
(SELECT Group_concat(`db_demandes`.`tbldemandes`.`montantsubside` SEPARATOR ' ')
 FROM   `db_demandes`.`tbldemandes`
 WHERE  ( `db_demandes`.`tbldemandes`.`montantsubside` =
          `db_demandes`.`bdd`.`ref` )
 ORDER  BY `db_demandes`.`tbldemandes`.`montantsubside`)
        AS `Montantsdemandes`,
(SELECT Group_concat(`db_demandes`.`tbldemandes`.`date_am_subside` SEPARATOR ' '
        )
 FROM   `db_demandes`.`tbldemandes`
 WHERE  ( `db_demandes`.`tbldemandes`.`date_am_subside` =
          `db_demandes`.`bdd`.`ref` )
 ORDER  BY `db_demandes`.`tbldemandes`.`date_am_subside`)
        AS `Dates_AM_demandes`,
(SELECT Group_concat(`db_demandes`.`tbldemandes`.`date_op_subside` SEPARATOR ' '
        )
 FROM   `db_demandes`.`tbldemandes`
 WHERE  ( `db_demandes`.`tbldemandes`.`date_op_subside` =
          `db_demandes`.`bdd`.`ref` )
 ORDER  BY `db_demandes`.`tbldemandes`.`date_op_subside`)
        AS `Dates_OP_demandes`,
`db_demandes`.`bdd`.`dtflagdeleted`
        AS `dtFlagDeleted`,
`db_demandes`.`tbldevis`.`dtdate`
        AS `dtDateDevis`,
`db_demandes`.`bdd`.`patrimoine`
        AS `Patrimoine`,
`db_demandes`.`bdd`.`telmobile`
        AS `TelMobile`,
`db_demandes`.`bdd`.`telprive`
        AS `TelPrive`,
`db_demandes`.`bdd`.`notes`
        AS `Notes`,
`db_demandes`.`bdd`.`notesagent`
        AS `NotesAgent`
 FROM   (((((`db_demandes`.`bdd`
             LEFT JOIN `db_demandes`.`tblsuivi`
                    ON(( `db_demandes`.`tblsuivi`.`fidossier` =
                      `db_demandes`.`bdd`.`ref` )))
            LEFT JOIN `db_demandes`.`tbldevis`
                   ON(( ( `db_demandes`.`tbldevis`.`fidossier` =
                        `db_demandes`.`bdd`.`ref` )
                        AND ( `db_demandes`.`tbldevis`.`iddevis` = (SELECT Max(
                              `db_demandes`.`tbldevis`.`iddevis`)
                                                                    FROM
                              `db_demandes`.`tbldevis`
                                                                    WHERE  (
                                    `db_demandes`.`tbldevis`.`fidossier` =
                            `db_demandes`.`bdd`.`ref` )) ) )))
           LEFT JOIN `db_demandes`.`tblvisites`
                  ON(( `db_demandes`.`tblvisites`.`fidossier` =
                     `db_demandes`.`bdd`.`ref` )))
          LEFT JOIN `db_demandes`.`tblvisites` `avantpromesse`
                 ON(( `avantpromesse`.`fidossier` =
         `db_demandes`.`bdd`.`ref` )))
         LEFT JOIN `db_demandes`.`vvisitemin`
                ON(( `vvisitemin`.`fidossier` = `db_demandes`.`bdd`.`ref` )))
 WHERE ( ( NOT(( Lcase(`db_demandes`.`bdd`.`nodossier`) LIKE '%avis%' )) )
          AND ( NOT(( Lcase(`db_demandes`.`bdd`.`nodossier`) LIKE '%dble%' )) )
        )
 GROUP  BY `db_demandes`.`bdd`.`nodossier`,
           `db_demandes`.`tblsuivi`.`idsuivi`
 ORDER  BY `db_demandes`.`bdd`.`nodossier` DESC);

然后由另一个 SQL 请求查询。因此,即使该组最大的表(表“bdd”)上只有 7000 条记录,我的性能也非常差。

正如你所看到的,有一些串联等等......让事情变得更加混乱

我真的需要提高性能,因为它需要几分钟才能显示。

你会从哪里开始?我不是 SQL 专家...还不是!

我试图摆脱一些

group_concat
不同的开始,但它太混乱了......我想有一些遗留功能可以优化

sql mysql select subquery group-concat
1个回答
0
投票

除了带有索引的表定义之外,您还应该为查询提供 MySQL

EXPLAIN
输出。

由于所有的反引号和额外不必要的括号,查询有点难以阅读。

首先,您可以检查相关表是否具有与其匹配的

db_demandes.bdd.ref
列的索引。

查询本身将对

db_demandes.bdd
表进行表扫描,因为
LIKE '%xxx%'
子句中有
WHERE

此外,

GROUP BY
看起来有点可疑,因为您在选择列表中有
db_demandes.bdd.id
,但您正在对其他列进行分组。

这是查询的清理版本:

SELECT    
  b.id                                                                   AS id,
  b.ref                                                                  AS ref,
  b.nodossier                                                            AS nodossier,
  b.agentfirme                                                           AS agentfirme,
  b.agentanterieur                                                       AS agentanterieur,
  Concat(b.nom, '\r\n', b.prenom)                                        AS demandeur,
  Concat(b.no_o, ' ', b.rue_o, '\r\n', b.cp_o, ' ', b.localite_o)  AS adresse,
  b.protection                                                           AS protection,
  b.type_objet                                                           AS type_objet,
  b.datation_o                                                           AS datation_o,
  b.datedemandesubsideavt                                                AS datedemandesubsideavt,
  Replace(b.datef1, '+', '\n')                                           AS datef1,
  Replace(b.datear1, '+', '\n')                                          AS datear1,
  b.datedemandeavise                                                     AS datedemandeavise,
  b.dateavisfirme_e                                                      AS dateavisfirme_e,
  b.dateavisfirme_o                                                      AS dateavisfirme_o,
  b.dtdatedemandeauthtrav                                                AS dtdatedemandeauthtrav,
  b.dtdatedecisiondirection                                              AS dtdatedecisiondirection,
  group_concat(DISTINCT avantpromesse.dtdate separator ' ')              AS v1,
  b.daterefusavt                                                         AS daterefusavt,
  b.email                                                                AS email,
  b.travaux_a_subventionner                                              AS travaux_a_subventionner,
  b.pc                                                                   AS pc,
  b.ff                                                                   AS ff,
  ( 
          SELECT   group_concat(tblpromesses.montantestimatifpromesse separator ' ') 
          FROM     tblpromesses 
          WHERE    tblpromesses.fidossier = b.ref
          ORDER BY tblpromesses.idpromesse) AS montantsestimatifs, 
  ( 
          SELECT   group_concat(tblpromesses.dtdatepromesse separator ' ' ) 
          FROM     tblpromesses 
          WHERE    tblpromesses.fidossier = b.ref
          ORDER BY tblpromesses.idpromesse)                              AS datespromesses,
  group_concat(DISTINCT tblvisites.dtdate separator ' ')                 AS visites,
  ts.dtavancementtravaux                                                 AS dtavancementtravaux,
  trim(concat(ts.dtobservations, '\r\n', 
     replace( ts.dtavancementtravaux, '\r\n', 'X'))
  )                                                                      AS dtobservations,
  ts.dtetat                                                              AS dtetat,
  b.paiementsprevisionnels2011                                           AS paiementsprevisionnels2011,
  b.paiementsprevisionnels2012                                           AS paiementsprevisionnels2012,
  replace(b.datef2, '+', '\n')                                           AS datef2,
  replace(b.datear2, '+', '\n')                                          AS datear2,
  b.daterefusap_t                                                        AS daterefusap_t,
  b.tt                                                                   AS tt,
  ( 
          SELECT group_concat(tbldemandes.montantsubside separator ' ') 
          FROM tbldemandes 
          WHERE tbldemandes.montantsubside = b.ref
          ORDER BY tbldemandes.montantsubside)                             AS montantsdemandes, 
  ( 
          SELECT group_concat(tbldemandes.date_am_subside separator ' ' ) 
          FROM tbldemandes 
          WHERE  tbldemandes.date_am_subside = b.ref 
          ORDER BY tbldemandes.date_am_subside
  )                                                                       AS dates_am_demandes, 
  ( 
          SELECT group_concat(tbldemandes.date_op_subside separator ' ' ) 
          FROM tbldemandes 
          WHERE tbldemandes.date_op_subside = b.ref
          ORDER BY tbldemandes.date_op_subside
  )                                                                       AS dates_op_demandes, 
  b.dtflagdeleted                                                         AS dtflagdeleted, 
  tbldevis.dtdate                                                         AS dtdatedevis, 
  b.patrimoine                                                            AS patrimoine, 
  b.telmobile                                                             AS telmobile, 
  b.telprive                                                              AS telprive, 
  b.notes                                                                 AS notes, 
  b.notesagent                                                            AS notesagent 
FROM db_demandes.bdd b
  LEFT JOIN tblsuivi ts ON ts.fidossier = b.ref 
  LEFT JOIN tbldevis ON tbldevis.fidossier = b.ref 
     AND tbldevis.iddevis = 
     ( 
            SELECT max( tbldevis.iddevis) 
            FROM   tbldevis 
            WHERE tbldevis.fidossier = b.ref
      )  
  LEFT JOIN tblvisites ON tblvisites.fidossier = b.ref
  LEFT JOIN tblvisites avantpromesse ON avantpromesse.fidossier = b.ref 
  LEFT JOIN vvisitemin ON vvisitemin.fidossier = b.ref
WHERE NOT( lcase(b.nodossier) LIKE '%avis%' ) AND NOT(lcase(b.nodossier) LIKE '%dble%' )  
GROUP BY b.nodossier, ts.idsuivi 
ORDER BY b.nodossier DESC;
© www.soinside.com 2019 - 2024. All rights reserved.