2013-02-08 63 views
0

对于下表,是否可以创建SQL语句来创建数据矩阵或视图?SQL语句 - SQL Matrix

表:

TeamA|TeamB|Won|Lost 
-------------------- 
    A | B | 5 | 3 
    A | C | 2 | 4 
    A | D | 9 | 1 
    B | E | 5 | 5 
    C | A | 2 | 4 

结果矩阵:

 | A | B | C | D | E 
---------------------------- 
    A | 0 | 2 | -2 | 8 | 0 
    B | 0 | 0 | 0 | 0 | 0 
    C | -2 | 0 | 0 | 0 | 0 
+2

它不会是太难的事它的五支球队的具体情况,但是这将扩展到任意数量的团队和游戏的一个通用的解决方案将是相当棘手单独使用sql。 – paul 2013-02-08 12:48:32

+3

数据库用于存放和获取数据,**不**可以很好地格式化数据。这是在表示层完成的! – fancyPants 2013-02-08 12:59:49

+0

@Megachip。 。 。这两个都是矩阵。他们只是代表不同。 – 2013-02-08 14:02:53

回答

1

有两种方法,你可以在枢轴数据在MySQL中。如果您事先知道这些值(团队),那么您将对这些值进行硬编码,或者您可以使用准备好的语句来生成动态SQL。

静态版本是:

select TeamA, 
    max(case when TeamB = 'A' then won - lost else 0 end) as A, 
    max(case when TeamB = 'B' then won - lost else 0 end) as B, 
    max(case when TeamB = 'C' then won - lost else 0 end) as C, 
    max(case when TeamB = 'D' then won - lost else 0 end) as D, 
    max(case when TeamB = 'E' then won - lost else 0 end) as E 
from yourtable 
group by TeamA; 

SQL Fiddle with Demo

如果你想使用一个事先准备好的声明动态版,代码如下:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(CASE WHEN TeamB = ''', 
     TeamB, 
     ''' THEN won - lost else 0 END) AS `', 
     TeamB, '`' 
    ) 
) INTO @sql 
from 
(
    select * 
    from yourtable 
    order by teamb 
) x; 

SET @sql 
    = CONCAT('SELECT TeamA, ', @sql, ' 
      from yourtable 
      group by TeamA'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

SQL Fiddle with Demo

编辑#1,在想到这个后,我实际上会做这个稍微有点不同。我会在队伍出现在行和列中的数据中生成一个真正的矩阵。要做到这一点,你会首先使用UNION ALL查询来获取所有的球队在两列:

select teama Team1, teamb Team2, 
    won-lost Total 
from yourtable 
union all 
select teamb, teama, 
    won-lost 
from yourtable 

SQL Fiddle with Demo。一旦做到这一点,那么你会支点数据:

select Team1, 
    coalesce(max(case when Team2 = 'A' then Total end), 0) as A, 
    coalesce(max(case when Team2 = 'B' then Total end), 0) as B, 
    coalesce(max(case when Team2 = 'C' then Total end), 0) as C, 
    coalesce(max(case when Team2 = 'D' then Total end), 0) as D, 
    coalesce(max(case when Team2 = 'E' then Total end), 0) as E 
from 
(
    select teama Team1, teamb Team2, 
    won-lost Total 
    from yourtable 
    union all 
    select teamb, teama, 
    won-lost 
    from yourtable 
) src 
group by Team1; 

SQL Fiddle with Demo。它给出了更详细的结果:

| TEAM1 | A | B | C | D | E | 
------------------------------- 
|  A | 0 | 2 | -2 | 8 | 0 | 
|  B | 2 | 0 | 0 | 0 | 0 | 
|  C | -2 | 0 | 0 | 0 | 0 | 
|  D | 8 | 0 | 0 | 0 | 0 | 
|  E | 0 | 0 | 0 | 0 | 0 | 
+0

迄今为止工作,但如果团队数字不是字符串,我会遇到麻烦...... – Megachip 2013-02-08 15:03:32

+0

@Megachip可以编辑sql提琴数据的样本?然后将该链接发布为评论。 – Taryn 2013-02-08 15:04:58

+0

http://www.sqlfiddle.com/#!2/40bb3/2可能存在引用问题? – Megachip 2013-02-08 15:08:24

1

您不能创建具有可变数量的列的SQL语句或视图。在标准SQL中,可以通过执行类似以下操作来转发数据:

select TeamA, 
     max(case when TeamB = 'A' then won - lost end) as A, 
     max(case when TeamB = 'B' then won - lost end) as B, 
     max(case when TeamB = 'C' then won - lost end) as C, 
     max(case when TeamB = 'D' then won - lost end) as D, 
     max(case when TeamB = 'E' then won - lost end) as E 
from t 
group by TeamA 
order by 1 

某些数据库支持一个pivot语句。

一般来说,您必须创建一个SQL语句作为字符串,然后执行它(通常称为动态 SQL)。这样的语句可以由SQL,存储过程,Excel或其他编程工具生成。然后它需要被执行。

让我重复一遍:任何给定的SQL语句都有一组预定义的列。你不能改变列的数量。

+0

好的,这是一个特定的...是否有可能做一些循环?或者是一个普通的声明是绝对不可能的? – Megachip 2013-02-08 14:34:04

+0

循环访问SQL中的数据不是一种情况。使用另一个级别(C#,PHP或您正在使用的其他语言)。 – 2013-02-08 14:39:49

+0

@RomanBadiornyi,正如问题所述,它是一个技术问题,而不是一个“使用问题” – Megachip 2013-02-08 18:25:28