【问题标题】:MySQl count grouping by 4 columnsMySQl 计数按 4 列分组
【发布时间】:2013-10-05 11:57:52
【问题描述】:

基本上,这个查询从 counts() 返回不同的值

Geographic Address(city),Office,Device type, Device unique type identifier, number case by device type
0001,1002,ORDENADOR,ORD1234,5 INCIDENCIAS
0001,1002,ORDENADOR,ORD3333,2 INCIDENCIAS
0001,1002,ORDENADOR,ORD2222,1 INCIDENCIAS
0001,1002,TECLADO,TECYYYY,2 INCIDENCIAS
0001,1002,TECLADO,TECXXXX,4 INCIDENCIAS
0001,1002,PANTALLA,PAN0000,1 INCIDENCIAS

Select 
        d.dt as 'Direccion Territorial',
        t.centro as 'Oficina',
        nombrelargo,
        if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina) as 'Oficina2',
        p.Tipo_Disp as 'Dispositivo',
        count(p.Tipo_Disp) as 'Nº de partes/Etiqueta',
        p.Etq_Amarilla as 'Etiqueta',
        ------------   count(TOTAL INC DE ESE DISPOSITIVO) ---------------------------,
        ------------   count(TOTAL INC DE ESA OFICINA) ---------------------------

from textcentro t,dtdz d,ppp p
        where 
                t.jcentro03=d.dt and
                t.organizativo='OFIC./AGEN./DELEG.' and
                t.situacion='ABIERTO' and
                t.sociedad='0900' and
                (p.Estado != "Abierto" and p.Estado!= 'Planificado') and
                (month(p.Fecha_y_hora_de_creacion) = 8 and year(Fecha_y_hora_de_creacion)=2013) and
                t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)

                GROUP BY d.dt,t.centro,p.Tipo_Disp,p.Etq_Amarilla

分组:

1 - d.dt ----> 邮政编码

2 - t.centro ----> 办公代码

3 - p.Tipo_Disp ----> 设备类型

4 - d.Etq_Amarilla ---->此设备的唯一标识符

表格是:

1- textcentro ----> 办事处的具体信息

2- dtdz ----> 辅助表查找办公室的邮政编码

3- ppp ----> 可以找到所有案例的表格

所以现在,我想按设备类型汇总案例总数,应该是这样的:

Postal Code,Office,Device type, Unique identifier for Device, total number of cases by unique identifier device, total number case by device type, total number case by office

0001,1002,ORDENADOR,ORD1234,5 INCIDENCIAS,8 INC,15
0001,1002,ORDENADOR,ORD3333,2 INCIDENCIAS,8 INC,15
0001,1002,ORDENADOR,ORD2222,1 INCIDENCIAS,8 INC,15
0001,1002,TECLADO,TECYYYY,2 INCIDENCIAS,6 INC,15
0001,1002,TECLADO,TECXXXX,4 INCIDENCIAS,6 INC,15
0001,1002,PANTALLA,PAN0000,1 INCIDENCIAS,1 INC,15

我正在尝试使用 sum 和 counts 函数,但我没有达到它,我没有任何方法可以获取最后两列。我认为我可以尝试通过列中的子查询来获取这个数字,但是性能会下降太多。

这个例子是这样的......但即使我完成了查询并且我等待了大约 12-13 分钟。

Select 
        d.dt as 'Direccion Territorial',
        t.centro as 'Oficina',
        nombrelargo,
        if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina) as 'Oficina2',
        p.Tipo_Disp as 'Dispositivo',
        count(p.Tipo_Disp) as 'Nº de partes/Etiqueta',
        p.Etq_Amarilla as 'Etiqueta',
        (Select count(*) from People_DB pp where pp.Oficina=p.Oficina and pp.Tipo_Disp=Dispositivo and (month(pp.Fecha_y_hora_de_creacion) = 8 and year(pp.Fecha_y_hora_de_creacion)=2013) and (pp.Estado != "Abierto" and pp.Estado!= 'Planificado') )

from textcentro t,dtdz d,ppp p
        where 
                t.jcentro03=d.dt and
                t.organizativo='OFIC./AGEN./DELEG.' and
                t.situacion='ABIERTO' and
                t.sociedad='0900' and
                (p.Estado != "Abierto" and p.Estado!= 'Planificado') and
                (month(p.Fecha_y_hora_de_creacion) = 8 and year(Fecha_y_hora_de_creacion)=2013) and
                t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)

                GROUP BY d.dt,t.centro,p.Tipo_Disp,p.Etq_Amarilla

对不起,我的英语不好,也许这篇文章难以理解

【问题讨论】:

  • 可能要添加索引看看EXPLAIN O/P

标签: mysql count group-by sum


【解决方案1】:

我可以提些建议吗:

首先,您选择的表格如下所示:

 from textcentro t,dtdz d,ppp p

为了清楚起见,我建议您改用显式的JOIN 语句。例如

 FROM textcentro AS t
 JOIN dtdx       AS d      ON t.jcentro03=d.dt
 JOIN ppp        AS p      ON  XXXXXXXXX

您可能想使用LEFT JOIN,例如,在 dtdx 中可能没有对应的行与 textcentro 中的行匹配的情况下。

无法从您的示例查询中判断 ON 到 ppp 的 JOIN 约束应该是什么。我在上面的代码中用XXXXXXXXX 证明了这一点。我认为你的情况是这样的:

 t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)

但这是一个令人讨厌的计算表达式,因此非常慢。看起来您的 t.centro 是一个 char 列,其中包含一个带前导零的整数,而您的 p.Oficina 是相同的,但没有前导零。不要将前导零添加到 p.Oficina,而是尝试从 t.centro 列中剥离它。

 CAST(t.centro AS INTEGER) = p.Oficina

请记住,如果没有简单的JOIN 约束,您会得到组合爆炸:m 乘以 n 行。这会使事情变得缓慢,甚至可能出错。

因此,您的表选择变为:

 FROM textcentro AS t
 JOIN dtdx       AS d      ON t.jcentro03=d.dt
 JOIN ppp        AS p      ON CAST(t.centro AS INTEGER) = p.Oficina

第二,您的日期/时间搜索表达式不是为了速度而构建的。试试这个:

      p.Fecha_y_hora_de_creacion >= '2013-08-01'
  AND p.Fecha_y_hora_de_creacion <  '2013-08-01' + INTERVAL 1 MONTH

如果您的p.Fecha... 列上有索引,这将允许对该列进行范围扫描搜索。

第三,您的SELECT 列表中的此项正在扼杀性能。

(Select count(*) 
   from People_DB pp 
  where pp.Oficina=p.Oficina 
    and pp.Tipo_Disp=Dispositivo
    and (month(pp.Fecha_y_hora_de_creacion) = 8 
    and year(pp.Fecha_y_hora_de_creacion)=2013) 
    and (pp.Estado != "Abierto" and pp.Estado!= 'Planificado') )

将其重构为 JOIN 列表中的虚拟表,如下所示。

 (SELECT COUNT(*) AS NumPersonas,
         Oficina,
         Tipo_Disp
    FROM People_DB
   WHERE Fecha_y_hora_de_creacion >= '2013-08-01'
     AND Fecha_y_hora_de_creacion <  '2013-08-01' + INTERVAL 1 MONTH
     AND Estado != 'Abierto'
     AND Estado != 'Planificado 
   GROUP BY Oficina, Tipo_Disp
 ) AS pp_summary ON (    pp_summary.Oficina=p.Oficina
                     AND pp_summary.Tipo_Disp=Dispositivo)

所以,这是您的最终表格列表。

 FROM textcentro AS t
 JOIN dtdx       AS d      ON t.jcentro03=d.dt
 JOIN ppp        AS p      ON CAST(t.centro AS INTEGER) = p.Oficina
 JOIN  (
         SELECT COUNT(*) AS NumPersonas,
                Oficina,
                Tipo_Disp
           FROM People_DB
          WHERE Fecha_y_hora_de_creacion >= '2013-08-01'
            AND Fecha_y_hora_de_creacion <  '2013-08-01' + INTERVAL 1 MONTH
            AND Estado != 'Abierto'
            AND Estado != 'Planificado 
       GROUP BY Oficina, Tipo_Disp
 ) AS pp_summary ON (    pp_summary.Oficina=p.Oficina
                     AND pp_summary.Tipo_Disp=Dispositivo)

其中三个表是“物理”表,第四个是“虚拟”表,构造为名为 People_DB 的物理表的摘要。

你可以包括

     pp_summary.NumPersonas

在您的 SELECT 列表中。

第四,避免MySQLGROUP BY功能的非标准扩展,使用标准SQL。阅读本文了解更多信息。

http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html

第五,为您的表添加适当的索引。

【讨论】:

  • 我已经尝试过您的建议,但即使我没有完成查询
  • 你的意思是查询没有完成运行?
  • 我成功了!谢谢你!
猜你喜欢
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多