交叉表 - 252个查询 - 优化

时间:2014-04-29 10:15:02

标签: mysql sql query-optimization

我在数据库中有5个表:

产品

应用

材料

产品与材料之间的关系(N:M)

产品与应用之间的关系(N:M)

我需要创建一个表格,其中包含:

Application 1 | Material 1 | Total products having application 1 + Material 1
Application 1 | Material 2 | Total products having application 1 + Material 2
Application 1 | Material 3 | Total products having application 1 + Material 3
Application 1 | Material N | Total products having application 1 + Material N

Application 2 | Material 1 | Total products having application 2 + Material 1
Application 2 | Material 2 | Total products having application 2 + Material 2
Application 2 | Material 3 | Total products having application 2 + Material 3
Application 2 | Material N | Total products having application 2 + Material N

Application N | Material 1 | Total products having application N + Material 1
Application N | Material 2 | Total products having application N + Material 2
Application N | Material 3 | Total products having application N + Material 3
Application N | Material N | Total products having application N + Material N

我有这个SQL,它向我显示完全正常。

SELECT A.APPLICATION_ID, A.APPLICATION_name_spanish, M.MATERIAL_ID, M.MATERIAL_name_spanish, COUNT(P.PRODUCT_ID)
FROM t_products P
LEFT JOIN t_products_materials PM ON P.PRODUCT_ID=PM.PRODUCT_ID
LEFT JOIN t_materials M ON PM.MATERIAL_ID=M.MATERIAL_ID
LEFT JOIN t_products_applications PA ON P.PRODUCT_ID=PA.PRODUCT_ID
LEFT JOIN t_applications A ON PA.APPLICATION_ID=A.APPLICATION_ID
GROUP BY A.APPLICATION_ID, M.MATERIAL_ID
ORDER BY A.APPLICATION_ID ASC, M.MATERIAL_ID ASC

但是,我没有采取交叉应用N +材料N的那些关系。总计= 0 PROCUT

如何获得材料x应用的完整列表,虽然这种关系的结果是零prductos?

此处带有表和内容的SQL:http://www.javiscript.es/images_foros/sql.sql

2 个答案:

答案 0 :(得分:0)

为此,您需要从所有可能的应用程序和材料对的列表开始。你可以使用交叉连接获得这个:

select a.application_id, a.application_name_spanish, m.material_id, m.material_name_spanish,
       count(pm.product_id)
from t_applications a cross join
     t_materials m left join
     t_products_applications pa
     on pa.application_id = a.application_id left join
     t_products_materials pm
     on pm.product_id = pa.product_id and
        pm.material_id = m.material_id;
group by a.application_id, a.application_name_spanish, m.material_id, m.material_name_spanish,
order by a.application_id, m.material_id;

作为备注,您实际上并不需要第五个表t_products。您可以将匹配用于t_products_materials,假设您的所有表都具有正确的外键关系。

答案 1 :(得分:0)

然后,我会预先查询材料和应用程序的所有组合(别名“AllMatApps”)。由于这似乎是一个相对较小的集合,我也得到应用程序和材料的相应“名称”值与之后再次重新加入。
辅助查询是预先聚合的ACTUAL材料和应用程序的连接。然后加入AllMatApps

    SELECT
          AllMatApps.APPLICATION_ID, 
          AllMatApps.APPLICATION_name_spanish, 
          AllMatApps.MATERIAL_ID, 
          AllMatApps.MATERIAL_name_spanish, 
          COALESCE( SUM( PMPA.PMPACount ), 0) as FinalCount
       from 
          ( SELECT 
                a.Application_ID,
                a.name_spanish,
                m.Material_ID,
                m.name_spanish
             from
                t_applications a 
                   cross join t_materials m ) AllMatApps
          LEFT JOIN
          ( select
                  PA.Application_ID,
                  PM.Material_ID,
                  COUNT(*) as PMPACount
               from
                  t_products_materials PM
                     JOIN t_products_applications PA
                        ON PM.PRODUCT_ID = PA.PRODUCT_ID
               group by
                  PA.Application_ID,
                  PM.Material_ID ) PMPA
             ON AllMatApps.Application_ID = PMPA.Application_ID
            AND AllMatApps.Material_ID = PMPA.Material_ID
   order by 
      AllMatApps.APPLICATION_ID, 
      AllMatApps.MATERIAL_ID