MySQL многомерный выбор из представлений - PullRequest
1 голос
/ 03 мая 2011

Я хотел бы отображать данные, перегруппированные год за годом, и одним из возможных решений является использование представлений и выбор из них.Матрица данных выглядит примерно так (конечно, это вымышленный набор демонстрационных данных):

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   

Есть идеи, как это сделать, включая строки с пропущенными данными?Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 03 мая 2011

Используйте левые соединения и представление (или таблицу, или внутренний выбор, как показано ниже), которое имеет все отдельные страны:

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

EDIT:

В более общем контексте вы просите создать сводную этой таблицы, которая является распространенной проблемой, которая имеет общие решения. Вот хорошее "How To": http://www.artfulsoftware.com/infotree/queries.php?&bw=1339#78

0 голосов
/ 04 мая 2011

Спасибо Galz за ссылку на сводки и спасибо ypercube за SQL. Это сработало после того, как годы заключили в кавычки, чтобы сделать их ЧАР.

Меня также заинтриговал вопрос, что произойдет, если я добавлю строку без значений или строку вне диапазона лет, поэтому я добавил

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

В результате я получил смесь нулевых и нулевых значений. Это не хорошо, потому что ноль - это действительное число и достоверные данные. Поэтому я изменил запрос, чтобы получить именно тот результат, который мне нужен:

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 голосов
/ 03 мая 2011

Лучше использовать JOIN, чем неявное 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...