MySQL-按“选择中的选择”结果分组

时间:2018-08-12 01:23:17

标签: mysql sql

我当前正在执行一个查询,该查询在选择中包含两个选择。我想对返回的结果进行分组以进行计数(进而创建饼图)

我要查询的系统包含一张图像表。每个图像可能具有零个或多个位元数据。可用的元数据因图像而异,因此它由单独的表而不是作为图像表的一部分的列提供服务。

所以表结构是:

Image {
   image_id (PK)
}

ImageMetaDataKey {
   metadata_key_id (PK),
   key
}

ImageMetaDataValue {
   metadata_value_id (PK),
   value
}

ImageMetaData {
   image_id (FK - Image.image_id),
   metadata_key_id (FK - ImageMetaDataKey.metadata_key_id ),
   metadata_value_id (FK - ImageMetaDataValue.metadata_value_id )
}

我当前的SQL语句是:

SELECT i_o.image_id, (SELECT imdv.value
    FROM Image i, ImageMetaDataValue imdv, ImageMetaDataKey imdk, ImageMetaData imd
    WHERE imdk.metadata_key_id = imd.metadata_key_id 
    AND imd.metadata_value_id =imdv.metadata_value_id  
    AND (imdk.key='Camera Model')
    AND i.image_id=imd.image_id
) as Camera, (SELECT imdv.value
    FROM Image i, ImageMetaDataValue imdv, ImageMetaDataKey imdk, ImageMetaData imd
    WHERE imdk.metadata_key_id = imd.metadata_key_id 
    AND imd.metadata_value_id =imdv.metadata_value_id  
    AND (imdk.key='Lens Model')
    AND i.image_id=imd.image_id
) as Lens
FROM Image i_o
GROUP BY i_o.image_id;

返回:

+----------+-----------------------+-------------------------------------+
| image_id | Camera                | Lens                                |
+----------+-----------------------+-------------------------------------+
|       11 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
|       15 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
|       24 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
|       28 | Canon EOS 450D        | EF16-35mm f/2.8L USM                |
|       29 | Canon EOS 450D        | EF16-35mm f/2.8L USM                |
|       34 | Canon EOS 450D        | EF-S18-55mm f/3.5-5.6 IS            |
|       35 | Canon EOS 450D        | EF-S18-55mm f/3.5-5.6 IS            |
|       37 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
|       43 | Canon EOS 7D          | EF-S17-55mm f/2.8 IS USM            |
|       48 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
|       49 | Canon EOS 450D        | EF70-200mm f/2.8L USM               |
|       50 | Canon EOS 450D        | EF70-200mm f/2.8L USM               |
+----------+-----------------------+-------------------------------------+

理想情况下,我想运行以下内容:

SELECT COUNT(i_o.image_id) as 'Count   ', (SELECT imdv.value
    FROM Image i, ImageMetaDataValue imdv, ImageMetaDataKey imdk, ImageMetaData imd
    WHERE imdk.metadata_key_id = imd.metadata_key_id 
    AND imd.metadata_value_id =imdv.metadata_value_id  
    AND (imdk.key='Camera Model')
    AND i.image_id=imd.image_id
) as Camera, (SELECT imdv.value
    FROM Image i, ImageMetaDataValue imdv, ImageMetaDataKey imdk, ImageMetaData imd
    WHERE imdk.metadata_key_id = imd.metadata_key_id 
    AND imd.metadata_value_id =imdv.metadata_value_id  
    AND (imdk.key='Lens Model')
    AND i.image_id=imd.image_id
) as Lens
FROM Image i_o
GROUP BY i_o.image_id, Camera, Lens;

将返回:

    +----------+-----------------------+-------------------------------------+
    | Count    | Camera                | Lens                                |
    +----------+-----------------------+-------------------------------------+
    |        5 | Canon EOS 450D        | EF-S17-55mm f/2.8 IS USM            |
    |        2 | Canon EOS 450D        | EF16-35mm f/2.8L USM                |
    |        2 | Canon EOS 450D        | EF-S18-55mm f/3.5-5.6 IS            |
    |        1 | Canon EOS 7D          | EF-S17-55mm f/2.8 IS USM            |
    |        2 | Canon EOS 450D        | EF70-200mm f/2.8L USM               |
    +----------+-----------------------+-------------------------------------+

2 个答案:

答案 0 :(得分:2)

我将使用两个聚合级别。首先获得两种模型:

SELECT imd.image_id,
       MAX(CASE WHEN imdk.key = 'Camera Model' THEN imdv.value END) as camera_model,
       MAX(CASE WHEN imdk.key = 'LENS Model' THEN imdv.value END) as lens_model
FROM ImageMetaData imd JOIN
     ImageMetaDataKey imdk
     ON imdk.metadata_key_id = imd.metadata_key_id JOIN
     ImageMetaDataValue imdv
     ON imd.metadata_value_id = imdv.metadata_value_id  
GROUP BY imd.image_id;

然后将其用作子查询来获取计数:

SELECT camera_model, lens_model, COUNT(*)
FROM (SELECT imd.image_id,
             MAX(CASE WHEN imdk.key = 'Camera Model' THEN imdv.value END) as camera_model,
             MAX(CASE WHEN imdk.key = 'LENS Model' THEN imdv.value END) as lens_model
      FROM ImageMetaData imd JOIN
           ImageMetaDataKey imdk
           ON imdk.metadata_key_id = imd.metadata_key_id JOIN
           ImageMetaDataValue imdv
           ON imd.metadata_value_id = imdv.metadata_value_id  
      GROUP BY imd.image_id
     ) cl
GROUP BY camera_model, lens_model;

非常重要地注意使用正确,显式,标准 JOIN语法。

答案 1 :(得分:1)

因为我发现这个问题很有趣,所以我对第一个查询的结果进行了反向工程,从而创建了SQLFiddle。然后,我像这样重写查询:

SELECT i.image_id,
       imdata1.value AS Camera,
       imdata2.value AS Lens
FROM Image i
JOIN (SELECT imd1.image_id, imdv1.value FROM ImageMetaData imd1
      JOIN ImageMetaDataKey imdk1 
        ON imdk1.metadata_key_id = imd1.metadata_key_id AND
           imdk1.key = 'Camera Model'
      JOIN ImageMetaDataValue imdv1
        ON imdv1.metadata_value_id = imd1.metadata_value_id
      ) AS imdata1 ON imdata1.image_id = i.image_id
JOIN (SELECT imd2.image_id, imdv2.value FROM ImageMetaData imd2
      JOIN ImageMetaDataKey imdk2
        ON imdk2.metadata_key_id = imd2.metadata_key_id AND
           imdk2.key = 'Lens Model'
      JOIN ImageMetaDataValue imdv2
        ON imdv2.metadata_value_id = imd2.metadata_value_id
      ) AS imdata2 ON imdata2.image_id = i.image_id

输出:

image_id    Camera              Lens
11          Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
15          Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
24          Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
28          Canon EOS 450D      EF16-35mm f/2.8L USM
29          Canon EOS 450D      EF16-35mm f/2.8L USM
34          Canon EOS 450D      EF-S18-55mm f/3.5-5.6 IS
35          Canon EOS 450D      EF-S18-55mm f/3.5-5.6 IS
37          Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
43          Canon EOS 7D        EF-S17-55mm f/2.8 IS USM
48          Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
49          Canon EOS 450D      EF70-200mm f/2.8L USM
50          Canon EOS 450D      EF70-200mm f/2.8L USM

我改写它的原因是将其放入更适合分组的形式:

SELECT COUNT(i.image_id) AS `Count`,
       imdata1.value AS Camera,
       imdata2.value AS Lens
FROM Image i
JOIN (SELECT imd1.image_id, imdv1.value FROM ImageMetaData imd1
      JOIN ImageMetaDataKey imdk1 
        ON imdk1.metadata_key_id = imd1.metadata_key_id AND
           imdk1.key = 'Camera Model'
      JOIN ImageMetaDataValue imdv1
        ON imdv1.metadata_value_id = imd1.metadata_value_id
      ) AS imdata1 ON imdata1.image_id = i.image_id
JOIN (SELECT imd2.image_id, imdv2.value FROM ImageMetaData imd2
      JOIN ImageMetaDataKey imdk2
        ON imdk2.metadata_key_id = imd2.metadata_key_id AND
           imdk2.key = 'Lens Model'
      JOIN ImageMetaDataValue imdv2
        ON imdv2.metadata_value_id = imd2.metadata_value_id
      ) AS imdata2 ON imdata2.image_id = i.image_id
GROUP BY Camera, Lens

输出:

Count   Camera              Lens
5       Canon EOS 450D      EF-S17-55mm f/2.8 IS USM
2       Canon EOS 450D      EF-S18-55mm f/3.5-5.6 IS
2       Canon EOS 450D      EF16-35mm f/2.8L USM
2       Canon EOS 450D      EF70-200mm f/2.8L USM
1       Canon EOS 7D        EF-S17-55mm f/2.8 IS USM