mysql 将行转置为列

Posted

技术标签:

【中文标题】mysql 将行转置为列【英文标题】:mysql trasnposing rows to columns 【发布时间】:2012-05-02 09:24:56 【问题描述】:

我需要将以下查询输出为 csv。

我可以轻松编写 php 逻辑来将行从我的 group_concat 列转置为列

不过,我热衷于将尽可能多的数据部分保留在数据库中,并尽量减少 php 端的操作。

我正在尝试查询中 group_concat 下面的两列。

问题是 life_stage 列的丰度值也返回。如果除了操作 group_concat 键值之外没有其他办法,那很好,我只是想仔细检查一下。提前致谢

SELECT 
`tr`.`tr_id_pk` as 'RecordKey',
`t`.`tax_name` as `TaxonName`,
`tr`.`tr_date` as 'Date',
`s`.`si_name` as 'SiteName',
`tr`.`tr_grid_reference` as 'GridReference',
`tr`.`tr_is_site_grid` as 'IsSiteGrid',
`r`.`rec_name` as 'Recorder',
`r`.`rec_email` as 'RecorderEmail',
`tr`.`tr_comment` as 'RecordComment',
`tr`.`tr_last_update` as 'LastUpdated',
`tr`.`tr_form_key` as 'FormKey',
`c`.`co_name` as 'County',
`vc`.`vc_name` as 'ViceCounty',
`h`.`hab_name` as 'Habitat',
GROUP_CONCAT(DISTINCT CONCAT_WS('=', `ra`.`ra_name`, `rad`.`rad_value`)) as 'RecordAttributeKeyValuePairs',
`rad`.`rad_value` AS `abundance`,
`rad`.`rad_value` AS `life_stage`
FROM
`taxon_record`as `tr`
    INNER JOIN
`taxon`as `t` ON `tr`.`tax_id_fk` = `t`.`tax_id_pk`
    INNER JOIN
`recorder`as `r` ON `tr`.`rec_id_fk` = `r`.`rec_id_pk`
    INNER JOIN
`site`as `s` ON `tr`.`si_id_fk` = `s`.`si_id_pk`
    LEFT JOIN
`county`as `c` ON `tr`.`co_id_fk` = `c`.`co_id_pk`
    LEFT JOIN
`vice_county`as `vc` ON `tr`.`vc_id_fk` = `vc`.`vc_id_pk`
    LEFT JOIN
`habitat`as `h` ON `tr`.`hab_id_fk` = `h`.`hab_id_pk`
    LEFT JOIN
(`record_attribute_data`as `rad`
INNER JOIN `record_attribute`as `ra` ON (`rad`.`ra_id_fk` = `ra`.`ra_id_pk`)) ON (`tr`.`tr_id_pk` = `rad`.`tr_id_fk`)
WHERE
`r`.`rec_email` = 'some_email@somewhere.com'
GROUP BY `tr`.`tr_id_pk`; 

【问题讨论】:

您应该确保问题显得响亮而清晰,而不是嵌入到一小段文字中。 感谢输入,我现在澄清了 每条记录是否具有完全相同数量的属性,具有相同的属性名称? 不幸的是,它是开放式的,所以有些可能有 3 个属性,有些可能有 5 个,依此类推。 【参考方案1】:

您希望执行的操作称为“透视”您的数据,并且某些其他 RDBMS 具有本机支持,但 mysql 不支持(根据设计,因为开发人员认为此类操作属于表示层)。

但是,正如您所暗示的,您可以构建一个相当糟糕的 MySQL 查询来手动执行旋转操作(需要为每个输出列将属性表连接到查询一次):

SELECT tr.tr_id_pk, abundance, life_stage -- etc.
  FROM taxon_record AS tr
  LEFT JOIN (
    SELECT rad.tr_id_fk, rad.rad_value AS abundance
    FROM
      record_attribute_data ra JOIN record_attribute rad
        ON rad.ra_id_fk = ra.ra_id_pk
    WHERE ra.ra_name = 'abundance'
  ) AS tAbundance ON tAbundance.tr_id_fk = tr.tr_id_pk
  LEFT JOIN (
    SELECT rad.tr_id_fk, rad.rad_value AS life_stage
    FROM
      record_attribute_data ra JOIN record_attribute rad
        ON rad.ra_id_fk = ra.ra_id_pk
    WHERE ra.ra_name = 'life_stage'
  ) AS tLife_Stage ON tLife_Stage.tr_id_fk = tr.tr_id_pk
  -- etc.

如果您选择走这条路,您可以使用 PHP 中的循环构造或 MySQL 中的预准备语句生成此查询,从而使您的生活稍微轻松一些。

【讨论】:

是的,这是我正在考虑的方法,但我只是在检查它们是否是我设法错过的更简单的方法。反正我猜不是。感谢您的意见,我很感激。干杯。【参考方案2】:

问题是您以不同的名称两次获取同一列吗?:

`rad`.`rad_value` AS `abundance`,
`rad`.`rad_value` AS `life_stage`

看起来你总是会得到同样的东西来丰富和 life_stage 那样。

【讨论】:

以上是关于mysql 将行转置为列的主要内容,如果未能解决你的问题,请参考以下文章

Tsql 将行转置为列,按列分组

Oracle SQL Developer:如何使用 PIVOT 函数将行转置为列

SQL Server JSON 将行转置为列

SQL将行转置为列(按键变量分组)?

Postgres 根据列值将行转置为列

CASE语句将行转置为列