【问题标题】:Convert column oriented data to line oriented data将面向列的数据转换为面向行的数据
【发布时间】:2020-02-10 11:16:40
【问题描述】:

我的表中有此架构下的数据 (AVG_TEAM 字段为 AVG(AVG_OK),其中 TEAM_ID = TEAM_ID in line 和 MONTH = MONTH in line

DRIVER_ID  | MONTH  | TEAM_ID  | AVG_OK  |  AVG_TEAM
----------------------------------------------------
     005     201901     XXXX      81          84
     005     201902     XXXX      84          82
     005     201903     XXXX      81          80
     005     201904     ZZZZ      84          75
     070     201901     RRRR      77          80
     070     201902     RRRR      80          80

etc    

有些人希望在整个月内跟踪每个驱动程序的演变。预期的架构是:

DRIVER_ID | TEAM_ID  | AVG_OK_MONTH1  |  AVG_OK_MONTH2  |  AVG_OK_MONTH3  |   ...  |  AVG_OK_MONTH12  | GLOBAL_AVG  |  TEAM_GLOBAL_AVG
    005       XXXX          81                84               81             ...          NULL               82            ?
    070       RRRR          77                80               NULL           ...          NULL              78.5           ?
etc

正如您很可能看到的那样,这种方法已经存在很大的缺陷,因为 TEAM_ID 可能会随着月份而变化,因此 AVG_TEAM 字段不能用于轻松计算 TEAM_GLOBAL_AVG 字段

但是假设我们消除了这个缺陷,并认为 TEAM_ID 不会改变。 我看不到将第一个模式转换为另一个模式的简单方法,无论是使用 SQL 还是使用 PHP(从未这样做过)。

我想到了一些在 PHP 中使用数组的非常难看的解决方案,但是必须有更好更简单的方法吗?欢迎任何见解。

【问题讨论】:

  • 这在 PHP 中可能比在 SQL 中更容易做到...
  • 这就是所谓的“pivot”——跟随标签。
  • 对于 MariaDB 中的数据透视,请参阅 stackoverflow.com/a/56670844/1766831

标签: php sql mariadb pivot-table


【解决方案1】:

我认为您可以使用条件聚合。假设month 是一个日期:

select driver_id,
       max(case when month(month) = 1 then avg_ok end) as avg_ok_1,
       max(case when month(month) = 2 then avg_ok end) as avg_ok_2,
       max(case when month(month) = 3 then avg_ok end) as avg_ok_3,
       max(case when month(month) = 4 then avg_ok end) as avg_ok_4
from t
where month >= '2019-01-01' and month < '2020-01-01'
group by driver_id;

否则,您可以使用字符串或日期函数执行类似的操作:

select driver_id,
       max(case when right(month, 2) = '01' then avg_ok end) as avg_ok_1,
       max(case when right(month, 2) = '02' then avg_ok end) as avg_ok_2,
       max(case when right(month, 2) = '03' then avg_ok end) as avg_ok_3,
       max(case when right(month, 2) = '04' then avg_ok end) as avg_ok_4
from t
where month >= '201901' and month < '202001'
group by driver_id;

【讨论】:

  • 月份如问题所写,格式为 YYYYMM .. 的 varchar 将尝试第二种解决方案并返回给您,谢谢
  • 效果很好,非常感谢(当计时器允许时会接受)
猜你喜欢
  • 2014-03-19
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 2017-09-25
相关资源
最近更新 更多