2011-05-03 38 views
1

我想显示数据逐年重新排列,其中一种可能的解决方案是使用视图并从中选择。数据矩阵是一样的东西(当然这是一个虚构的演示数据集):从视图中选择MySQL多维

USA 2005 22 156 
CAN 2005 14 101 
MEX 2005 5 32 
USA 2006 24 160 
CAN 2006 16 103 
USA 2007 26 163 
MEX 2007 8 35 

的SQL代码来创建和填充表:

DROP TABLE IF EXISTS `tab1`;<br> 
CREATE TABLE `tab1` (<br> 
    `id1` int(4) unsigned NOT NULL AUTO_INCREMENT, 
    `iso3` char(3) NOT NULL, 
    `year` int(4) unsigned NOT NULL, 
    `aaa` int(10) DEFAULT NULL, 
    `bbb` int(10) DEFAULT NULL, 
    PRIMARY KEY (`id1`) 
) 


INSERT INTO `tab1` VALUES 
('1', 'USA', '2005', '22', '156'), 
('2', 'CAN', '2005', '14', '101'), 
('3', 'MEX', '2005', '5', '32'), 
('4', 'USA', '2006', '24', '160'), 
('5', 'CAN', '2006', '16', '103'), 
('6', 'USA', '2007', '26', '163'), 
('7', 'MEX', '2007', '8', '35'); 
COMMIT; 

现在我想获得的参数“AAA”一个二维表是这样的:

country 2005 2006 2007 
USA  22 24 26 
CAN  14 16   
MEX  5 8 

但是下面的SQL代码省略所有缺少数据的线,无论是一个单一的价值,我只得到一个行

USA 22 24 26 

的SQL代码:

SELECT view2005.Country, view2005.2005, view2006.2006, view2007.2007 
FROM view2005, view2006, view2007 
WHERE view2005.country = view2006.country 
AND view2005.country = view2007.country 

任何想法如何做到这一点,包括缺失数据线?提前致谢。

回答

0

最好使用JOIN而不是隐式加入WHERE。额外的优点是你可以将它转换为LEFT JOIN,因此2005年的数据没有2006相关行(并且不匹配)仍然会显示。

使用Galz的解决方案或搜索正确建议如何创建PIVOT查询。


一个这样的逻辑来创建一个支点查询将是:

SELECT iso3 AS Country 
     , SUM(IF(year=2005, aaa, 0)) AS 2005 
     , SUM(IF(year=2006, aaa, 0)) AS 2006 
     , SUM(IF(year=2007, aaa, 0)) AS 2007 
FROM tab1 AS t 
GROUP BY iso3 

如果有几年没有任何数据,您将在该列得到NULL
可以使用COALESCE()功能,如果你想0中显示,而不是NULL

SELECT iso3 AS Country 
     , COALESCE(SUM(IF(year=2004, aaa, 0)) , 0) AS "2004" 
     , COALESCE(SUM(IF(year=2005, aaa, 0)) , 0) AS "2005" 
     , COALESCE(SUM(IF(year=2006, aaa, 0)) , 0) AS "2006" 
     , COALESCE(SUM(IF(year=2007, aaa, 0)) , 0) AS "2007" 
FROM tab1 AS t 
GROUP BY iso3 
+0

那些没有2005年数据的国家呢? – Galz 2011-05-03 16:00:23

+0

是的,这不是一个好的尝试,删除它。发布新的一个。 – 2011-05-03 16:19:59

2

使用左联接和视图(或表,或内选择如下图所示),其中有所有不同的国家:

SELECT c.country, view2005.2005, view2006.2006, view2007.2007 
FROM (SELECT DISTINCT country FROM tab1) as c 
LEFT JOIN view2005 ON view2005.country = c.country 
LEFT JOIN view2006 ON view2006.country = c.country 
LEFT JOIN view2007 ON view2007.country = c.country 
GROUP BY c.country 

编辑:

在更普遍的情况下,你问这里是创建一个枢轴这张表,这是一个常见的问题,有共同的解决方案。这里是一个很好的“如何”:http://www.artfulsoftware.com/infotree/queries.php?&bw=1339#78

0

谢谢Galz的枢纽链接,谢谢ypercube的SQL。它在将年份放入引号以使其成为CHAR之后起作用。

我被我是否添加一行在全部或没有值的行出来的年,所以我加入

INSERT INTO `tab1` VALUES 
('7', 'ATA', '2004', '', '') 

的结果是,我得到了一个范围怎么办的问题进一步感兴趣NULL和INT零值的混合。这是不好的,因为零是一个有效的数字和合法的数据。所以我修改了查询以获得我需要的结果:

SELECT iso3 AS countryб 
     SUM(IF(year=2004, aaa, NULL)) AS "2004", 
     SUM(IF(year=2005, aaa, NULL)) AS "2005", 
     SUM(IF(year=2006, aaa, NULL)) AS "2006", 
     SUM(IF(year=2007, aaa, NULL)) AS "2007" 
FROM tab1 
GROUP BY iso3 
+0

如果你想显示'0'而不是'NULL',你可以使用'COALESCE()'函数。 – 2011-05-04 15:04:44