4

我在 MySQL 中有一个包含以下字段的表:

id, company_name, year, state

同一客户和年份有多行,以下是数据示例:

    id | company_name  | year | state
----------------------------------------
    1  | companyA      | 2008 | 1
    2  | companyB      | 2009 | 2
    3  | companyC      | 2010 | 3
    4  | companyB      | 2009 | 1
    5  | companyC      | NULL | 3

我正在尝试从此表中创建一个视图,以显示每行一家公司(即GROUP BYpubco_name),其中状态为给定年份的最高值。

这是我尝试创建的视图示例:

    id | cuompany_name | NULL | 2008 | 2009 | 2010
--------------------------------------------------
    1  | companyA      | NULL | 1    | NULL | NULL
    2  | companyB      | NULL | 2    | NULL | NULL
    3  | companyC      | 3    | NULL | NULL | 3

还有比这更多的数据,但你可以看到我想要完成的事情。

我不知道如何选择每年的最大状态并按 pubco_name 分组。这是我到目前为止的 SQL(我认为我们需要在这里使用CASE和/或sub-selects):

SELECT
id,
company_name,
SUM(CASE WHEN year = 2008 THEN max(state) ELSE 0 END) AS 2008,
SUM(CASE WHEN year = 2009 THEN max(state) ELSE 0 END) AS 2009,
SUM(CASE WHEN year = 2010 THEN max(state) ELSE 0 END) AS 2010,
SUM(CASE WHEN year = 2011 THEN max(state) ELSE 0 END) AS 2011,
SUM(CASE WHEN year = 2012 THEN max(state) ELSE 0 END) AS 2012,
SUM(CASE WHEN year = 2013 THEN max(state) ELSE 0 END) AS 2013
FROM tbl
GROUP BY company_name
ORDER BY id DESC

提前感谢您的帮助和感谢。

4

2 回答 2

1

您需要对表进行透视,但 mysql 没有任何这样的透视功能

所以我们需要复制它的功能

已编辑

Select 
  group_concat(
    DISTINCT 
       if(year is null,
          CONCAT('max(if (year is null, state, 0)) as ''NULL'' '),
          CONCAT('max(if (year=''', year, ''', state, 0)) as ''',year, ''' '))
    ) into @sql from tbl join (SELECT @sql:='')a;
set @sql = concat('select company_name, ', @sql, 'from tbl group by company_name;');
PREPARE stmt FROM @sql;
EXECUTE stmt;

结果

| COMPANY_NAME | 2008 | 2009 | 2010 | NULL |
--------------------------------------------
|     companyA |    1 |    0 |    0 |    0 |
|     companyB |    0 |    2 |    0 |    0 |
|     companyC |    0 |    0 |    3 |    3 |

SQL 小提琴

有两种方法可以解决您的问题 1. 为每年创建案例,这在您的情况下是不可能的,因为我们正在处理第 2 年。动态生成查询,以便我们根据您的需要获得适当的列。

我根据生成查询并将其存储在@sql变量中的第二种解决方案给出了解决方案。在小提琴中,我@sql在执行之前打印了它的内容。

select company_name, max(if (year='2008', state, 0)) as '2008' ,max(if (year='2009', state, 0)) as '2009' ,max(if (year='2010', state, 0)) as '2010' ,max(if (year is null, state, 0)) as 'NULL' from tbl group by company_name; 

有关group_concat()通过链接 GROUP_CONCATUSER DEFINED VARIABLE的更多信息

希望这可以帮助..

于 2013-04-05T11:07:44.023 回答
0

请参阅此问题答案中链接的页面。

请注意,执行此操作时,您必须提前指定输出中所需的列数。

针对下面的评论,这里是一个简单/基本的实现,它重现了上面的结果表(除了 ID 列;没有意义,因为结果中的每一行可以汇总输入表中的多行)

SELECT
   `company_name`,
   NULLIF(SUM(CASE WHEN `t3`.`year` IS NULL THEN `t3`.`state` ELSE 0 END), 0) AS `null`,
   NULLIF(SUM(CASE WHEN `t3`.`year` = 2008 THEN `t3`.`state` ELSE 0 END), 0) AS `2008`,
   NULLIF(SUM(CASE WHEN `t3`.`year` = 2009 THEN `t3`.`state` ELSE 0 END), 0) AS `2009`,
   NULLIF(SUM(CASE WHEN `t3`.`year` = 2010 THEN `t3`.`state` ELSE 0 END), 0) AS `2010`
FROM
(
   SELECT
   `t1`.`id`,
   `t1`.`company_name`,
   `t1`.`year`,
   `t1`.`state`
   FROM `tbl` `t1`
   WHERE `t1`.`state` = (
      SELECT MAX(`state`)
      FROM `tbl` `t2`
      WHERE `t2`.`company_name` = `t1`.`company_name`
      AND (`t2`.`year` IS NULL AND `t1`.`year` IS NULL OR `t2`.`year` = `t1`.`year`)
   )
) `t3`
GROUP BY `t3`.`company_name`;

这使用嵌套查询:内部查询(带有t1t2别名)查找每个年份和公司的最大状态行(除非您可以确定这是唯一的,否则它将中断!),外部t3查询.

我会对此进行彻底测试,以确保在真实数据上的性能是可以接受的。

于 2013-04-05T10:33:20.207 回答