将具有相同 id 的行合并为一行,保留所有数据

Posted

技术标签:

【中文标题】将具有相同 id 的行合并为一行,保留所有数据【英文标题】:Combined rows with same id in to one row keeping all data 【发布时间】:2012-11-04 09:27:38 【问题描述】:

我有一张包含许多植物记录的表格。一个植物可以有多个名称,该表将其显示为不同的记录。该表名为 new_plantsname

plantid name
1       tree
1       rose
2       bush
3       tree
3       bush
3       rose

这会持续超过 3000 条记录

我想要的是合并具有相同植物 ID 的记录并在不同的列中显示不同的名称:

plantid name1 name2 name3 ...
1       tree  rose  NULL
2       shrub NULL  NULL
3       tree  rose  bush 

等等

我还想将结果保存到新表中

【问题讨论】:

select group_concat(name) from new_plantsname group by plantid 会这样做吗? (假设 mysql 找到植物的最大 ID 然后使用 PIVOT 有用吗? 【参考方案1】:

这基本上是一个PIVOT(你没有指定RDBMS)我假设MySQL并且它没有PIVOT函数,所以你需要使用带有CASE语句的聚合函数来复制它。此解决方案将rownumber 添加到每一行,以便您确定需要转换为列的name 值。

如果您知道您将拥有多少个name 值,您可以对这些值进行硬编码:

select plantid,
  max(case when nameRn = 'name1' then name end) Name1,
  max(case when nameRn = 'name2' then name end) Name2,
  max(case when nameRn = 'name3' then name end) Name3
from
(
  select plantid, name,
      concat('name', @num := if(@plantid = `plantid`, @num + 1, 1)) as nameRn,
      @plantid := `plantid` as dummy
  from
  (
    select plantid, name, @rn:=@rn+1 overall_row_num
    from yourtable, (SELECT @rn:=0) r
  ) x
  order by plantid, overall_row_num
) src
group by plantid;

见SQL Fiddle with Demo

如果你有未知数量的值,那么你可以使用准备好的语句来生成这个的动态版本:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when nameRn = ''',
      nameRn,
      ''' then name end) AS ',
      nameRn
    )
  ) INTO @sql
FROM 
(
  select plantid, name,
      concat('name', @num := if(@plantid = `plantid`, @num + 1, 1)) as nameRn,
      @plantid := `plantid` as dummy
  from
  (
    select plantid, name, @rn:=@rn+1 overall_row_num
    from yourtable, (SELECT @rn:=0) r
  ) x
  order by plantid, overall_row_num
) src;


SET @sql = CONCAT('SELECT plantid, ', @sql, ' 
                  FROM 
                  (
                    select plantid, name,
                        concat(''name'', @num := if(@plantid = `plantid`, @num + 1, 1)) as nameRn,
                        @plantid := `plantid` as dummy
                    from
                    (
                      select plantid, name, @rn:=@rn+1 overall_row_num
                      from yourtable, (SELECT @rn:=0) r
                    ) x
                    order by plantid, overall_row_num
                  ) src
                   GROUP BY plantid');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

见SQL Fiddle with Demo

两者都会产生相同的结果:

| PLANTID | NAME1 |  NAME2 |  NAME3 |
-------------------------------------
|       1 |  tree |   rose | (null) |
|       2 |  bush | (null) | (null) |
|       3 |  tree |   bush |   rose |

【讨论】:

谢谢,这很好,会投票回答,但新网站还不能 我在 wamp phpmyadmin 中执行此操作并收到错误:#1243 - 提供给 EXECUTE 的未知准备语句处理程序 (stmt) @zaratjlc 我无法重现您所说的错误。 @zaratjlc 我不确定你为什么不接受这个答案,然后就你的问题发布了一个新问题。 抱歉,一位朋友告诉我,如果它在关闭问题时无法不接受答案,我收到的代码有错误:#1243 - 未知的准备好的语句处理程序 (stmt) 给执行

以上是关于将具有相同 id 的行合并为一行,保留所有数据的主要内容,如果未能解决你的问题,请参考以下文章

在SQL Server中将多行相同id的行合并为一行[关闭]

当数据集的列具有不同的行数时合并它们

合并具有相同 ID 变量的行 [重复]

我想要在一行中具有相同 ID 的行数据

Pandas DataFrame:合并具有相同 ID 的行

2015.12.24(圣诞节) 解决Oralce数据库将具有相同属性的多行合并为一行的简单方法多年想要wmsys.wm_concat