【问题标题】:MySQL - Grouping By results from Selects in SelectsMySQL - 按 Selects 中 Selects 的结果分组
【发布时间】:2018-08-12 01:23:17
【问题描述】:

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

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

所以表结构是:

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               |
    +----------+-----------------------+-------------------------------------+

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    我会使用两个级别的聚合。先拿到两个模型:

    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 语法的使用。

    【讨论】:

    • 很好地使用MAXGROUP BY 来避免双重连接。
    【解决方案2】:

    因为我发现这个问题很有趣,所以我通过对您的第一个查询的结果进行逆向工程创建了一个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
    

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      • 2019-07-13
      • 1970-01-01
      • 2010-11-17
      相关资源
      最近更新 更多