【问题标题】:MySQL table "pivot" without creating tables/views: unique column values as headerMySQL 表“透视”而不创建表/视图:唯一列值作为标题
【发布时间】:2018-12-30 21:39:55
【问题描述】:

我有这个“职业”两列表格,包含多个人的姓名和职业。职业是已知的,只能是“开发人员”、“工程师”、“医生”、“音乐家”。

Name   | Occupation
Dan    | Developer
Martin | Doctor
Sam    | Engineer
Andre  | Musician
Tom    | Engineer

目的是获得类似以下的东西:

Doctor | Engineer | Developer | Musician
Martin |    Sam   |   Dan     |  Andre
NULL   |    Tom   |   NULL    |   NULL

所有列都应按字母顺序排列。

你们对我如何使用 MySQL 实现这一点(不创建表、视图)有什么建议吗?

非常感谢!

【问题讨论】:

  • 看看SQL代码有多丑?在应用程序代码中执行此操作!
  • 完全同意@RickJames。不仅代码丑陋,而且缺乏灵活性。如果职业多于4个,你会怎么做?您需要添加多少代码?在 sql 中这样做的唯一原因可能是表中有大量数据。
  • @forpas - 如果有“非常大量”的数据,那么输出将是“非常大”。那时,我会严重批评 UI 决定有 4 个非常高的列表。
  • @RickJames 与获取整个数据并进行过滤相比,您不认为应该就地操作大量数据并仅将结果获取到终端(pc) /在那里处理?

标签: mysql sql database pivot-table


【解决方案1】:

这很痛苦,但您可以使用变量和聚合来做到这一点:

select max(doctor) as doctor,
       max(engineer) as engineer,
       max(developer) as developer,
       max(musician) as musician
from ((select name as doctor, null as engineer, null as developer, null as musician,
              (@rnd := @rnd + 1) as rn
       from t cross join
            (select @rnd := 0) as params
       where occupation = 'doctor'
      ) union all
      (select null as doctor, name as engineer, null as developer, null as musician,
              (@rne := @rne + 1) as rn
       from t cross join
            (select @rne := 0) as params
       where occupation = 'engineer'
      ) union all
      (select null as doctor, null as engineer, name as developer, null as musician,
              (@rnv := @rnv + 1) as rn
       from t cross join
            (select @rnv := 0) as params
       where occupation = 'developer'
      ) union all
      (select null as doctor, null as engineer, null as developer, name as musician,
              (@rnm := @rnm + 1) as rn
       from t cross join
            (select @rnm := 0) as params
       where occupation = 'musician'
      ) union all
     ) o
group by rn;

【讨论】:

    【解决方案2】:

    这将在 MySql 8.0 中工作:

    with occup as (
    select
      case when o.occupation = 'Doctor' then o.Name end as Doctor, 
      case when o.occupation = 'Engineer' then o.Name end as Engineer,
      case when o.occupation = 'Developer' then o.Name end as Developer,  
      case when o.occupation = 'Musician' then o.Name end as Musician
    from occupations o
    ),
    
    doctors as (
    select ROW_NUMBER() OVER (
     ORDER BY case when occup.Doctor is null then 1 else 0 end
     ) as rn, occup.Doctor from occup
    ),
    engineers as (
    select ROW_NUMBER() OVER (
     ORDER BY case when occup.Engineer is null then 1 else 0 end
     ) as rn, occup.Engineer from occup
    ),
    developers as (
    select ROW_NUMBER() OVER (
     ORDER BY case when occup.Developer is null then 1 else 0 end
     ) as rn, occup.Developer from occup
    ),
    musicians as (
    select ROW_NUMBER() OVER (
     ORDER BY case when occup.Musician is null then 1 else 0 end
     ) as rn, occup.Musician from occup
    )
    
    select doctors.Doctor, engineers.Engineer, developers.Developer, musicians.Musician 
    from doctors
    inner join engineers on doctors.rn = engineers.rn  
    inner join developers on engineers.rn = developers.rn
    inner join musicians on musicians.rn = developers.rn
    WHERE coalesce(doctors.Doctor, engineers.Engineer, developers.Developer, musicians.Musician) IS NOT NULL;
    

    demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-20
      • 2020-10-23
      • 1970-01-01
      • 2014-05-12
      • 2018-03-26
      • 2020-08-20
      • 2020-12-20
      • 1970-01-01
      相关资源
      最近更新 更多