【问题标题】:Group data from two tables, multiple columns and rows, into one row将两个表(多列和多行)中的数据分组为一行
【发布时间】:2013-03-28 20:17:06
【问题描述】:

我正在尝试将各自所在行的键 = 值对分组为按 ID 分组的一行。

表 1. wp_posts
键:ID - post_title

表 2. wp_postmeta
键:post_id、wpcf-owner、wpcf-tel、wpcf-mob、wpcf-email...

使用此查询,我得到了所有信息,但对于每个键,我得到单独的行。我需要的是一个数组,其中所有内容都在一行中,按 wp_posts.ID 分组

SELECT wp_posts.ID, wp_posts.post_title, wp_postmeta.post_id, wp_postmeta.meta_key, wp_postmeta.meta_value
FROM wp_posts
JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_posts.post_type = 'accommodation' AND wp_postmeta.meta_key LIKE 'wpcf%'
ORDER BY hic13_posts.post_title

结果是:

ID | post_title | key value  
------------------------------  
1  |  TITLE     |  wpcf-owner  
1  |  TITLE     |  wpcf-tel  
1  |  TITLE     |  wpcf-mob  
1  |  TITLE     |  wpcf-email  
2  |  TITLE     |  wpcf-owner  
2  |  TITLE     |  wpcf-tel  
2  |  TITLE     |  wpcf-mob  
2  |  TITLE     |  wpcf-email  
...

我需要的是:

ID | post_title | key value  | key value | key value | key value  
-----------------------------------------------------------------  
1  |  TITLE     | wpcf-owner | wpcf-tel  | wpcf-mob  | wpcf-email  
2  |  TITLE     | wpcf-owner | wpcf-tel  | wpcf-mob  | wpcf-email 

如果我将命令添加到按 ID 分组,那么我只能从第二个表中获得一个键...

SELECT wp_posts.ID, wp_posts.post_title, wp_postmeta.post_id, wp_postmeta.meta_key, wp_postmeta.meta_value
FROM wp_posts
JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_posts.post_type = 'accommodation' AND wp_postmeta.meta_key LIKE 'wpcf%'    
GROUP BY hic13_posts.ID
ORDER BY hic13_posts.post_title

我只得到这个

ID | post_title | key value  
------------------------------  
1  |  TITLE     |  wpcf-owner  
2  |  TITLE     |  wpcf-tel 

希望这一切都有意义:-)
谢谢!

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    这种类型的转换是 pivot,但 MySQL 没有枢轴函数,因此您需要使用带有 CASE 表达式的聚合函数。:

    SELECT p.ID, 
      p.post_title, 
      m.post_id, 
      max(case when m.meta_key = 'wpcf-owner' then m.meta_value end) as owner,
      max(case when m.meta_key = 'wpcf-tel' then m.meta_value end) as tel,
      max(case when m.meta_key = 'wpcf-mob' then m.meta_value end) as mob,
      max(case when m.meta_key = 'wpcf-email' then m.meta_value end) as email
    FROM wp_posts p
    JOIN wp_postmeta m
      ON p.ID = m.post_id
    WHERE p.post_type = 'accommodation' AND m.meta_key LIKE 'wpcf%'    
    GROUP BY p.ID, p.post_title, m.post_id
    ORDER BY p.post_title
    

    编辑,如果你有未知数量的meta_key项目要转换,那么你可以使用准备好的语句来生成动态sql:

    SET @sql = NULL;
    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'max(CASE WHEN m.meta_key = ''',
          meta_key,
          ''' THEN m.meta_value else null END) AS `',
          meta_key, '`'
        )
      ) INTO @sql
    FROM wp_postmeta;
    
    SET @sql 
      = CONCAT('SELECT p.ID, 
                  p.post_title, 
                  m.post_id, ', @sql, ' 
                FROM wp_posts p
                JOIN wp_postmeta m
                  ON p.ID = m.post_id
                WHERE p.post_type = ''accommodation'' 
                   AND m.meta_key LIKE ''wpcf%''   
                GROUP BY p.ID, p.post_title, m.post_id
                ORDER BY p.post_title');
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    【讨论】:

    • 代码生成错误,但删除部分 'AND p.meta_key LIKE 'wpcf%'' 修复它...还有一件事,有没有办法不为每个 meta_key 提供案例,因为有不少,并使其成为未来的证明。所有的键都以'wpcf-'开头,因此我有这部分'AND p.meta_key LIKE 'wpcf%''
    • @ronimarin 错误是因为我在 where 子句中的 meta_key 上放置了错误的表别名。我还编辑了我的答案,以包含为未知数量的列生成动态 sql 的解决方案。
    • 非常感谢,已经学习 SQL 几个小时才能做到这一点 ;-) 你确实为我节省了好几个小时!
    • @ronimarin 如果您在 SQL Server 中运行此代码,它将无法工作。
    • @ronimarin 此代码是 MySQL 特定的,您必须在 mysql 存储过程或某种 MySQL 接口中运行它。
    猜你喜欢
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    相关资源
    最近更新 更多