MySQL - 行到列并保持NULL

时间:2016-07-01 00:20:30

标签: mysql null pivot-table

我们在MySQL数据库(MySQL 5.6)中有以下表(TEST2):

 TEAM_ID,MEMBER_ID,TYPE,SCORE
 1,2,A,150
 1,3,B,200
 1,1,B,50
 1,1,A,100
 1,2,B,NULL

我们尝试根据TYPE列转换/转动上表:

如果TYPE列的值为== A,请将SCORE列中的值移动到名为A_SCORE的新列中。如果SCORE列中的值为NULL,则它应在新的A_SCORE列中显示NULL。

如果TYPE列的值为== B,请将SCORE列中的值移动到名为B_SCORE的新列中。如果SCORE列中的值为NULL,则它应在新的B_SCORE列中显示NULL。

下表是我们正在寻找的表(想要的表):

 TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
 1,1,100,50,50
 1,2,150,NULL,NULL
 1,3,0,200,-200

我们尝试了以下查询

 SELECT TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,SUM(A_SCORE-B_SCORE) AS ACTUAL_MINUS_B_SCORE FROM
  (SELECT TEAM_ID,MEMBER_ID,

 CASE
 WHEN SCORE IS NULL
 THEN NULL
 ELSE SUM(if(TYPE = 'A', SCORE,0) )
 END A_SCORE,

 CASE
 WHEN SCORE IS NULL
 THEN NULL
 ELSE SUM(if(TYPE = 'B', SCORE,0) )
 END B_SCORE
 FROM TEST2
 GROUP BY TEAM_ID,MEMBER_ID,SCORE) AS A
 GROUP BY TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE);

它会返回我们不想要的东西:

 TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
 1,1,0,50,-50
 1,1,100,0,100
 1,2,0,0,0
 1,2,150,0,150
 1,3,0,200,-200

如果我们尝试以下操作,它会生成一个接近我们想要的表,但它不会返回任何NULL值。

 SELECT TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,SUM(A_SCORE-B_SCORE) AS A_SCORE _MINUS_B_SCORE FROM
  (SELECT TEAM_ID,MEMBER_ID,

 SUM(if(TYPE = 'A', SCORE,0) ) AS A_SCORE,

 SUM(if(TYPE = 'B', SCORE,0) )AS B_SCORE
 FROM TEST2
 GROUP BY TEAM_ID,MEMBER_ID) AS A
 GROUP BY TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE;

上述查询的结果:

 TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
 1,1,100,50,50
 1,2,150,0,0
 1,3,0,200,-200

在这种情况下,使用MySQL可以让任何大师启发如何生成所需的表吗?为方便起见,SQL小提琴就在这里。

http://sqlfiddle.com/#!9/cfe7a1/1

谢谢!

2 个答案:

答案 0 :(得分:1)

试试这个;)

SELECT TEAM_ID, MEMBER_ID, A_SCORE, B_SCORE, A_SCORE - B_SCORE AS A_SCORE_MINUS_B_SCORE
FROM (
    SELECT
        TEAM_ID, MEMBER_ID,
        CASE
            WHEN A_SCORE IS NULL AND NOT EXISTS (
                SELECT 1 FROM TEST2 
                WHERE TEAM_ID = T1.TEAM_ID 
                AND MEMBER_ID = T1.MEMBER_ID
                AND TYPE = 'A'
            ) THEN 0 ELSE A_SCORE END AS A_SCORE,
        CASE
            WHEN B_SCORE IS NULL AND NOT EXISTS (
                SELECT 1 FROM TEST2 
                WHERE TEAM_ID = T1.TEAM_ID 
                AND MEMBER_ID = T1.MEMBER_ID
                AND TYPE = 'A'
            ) THEN 0 ELSE B_SCORE END AS B_SCORE
    FROM (
        SELECT
           TEAM_ID, MEMBER_ID,
           MAX(CASE WHEN TYPE = 'A' THEN SCORE END) AS A_SCORE,
           MAX(CASE WHEN TYPE = 'B' THEN SCORE END) AS B_SCORE
        FROM TEST2
        GROUP BY TEAM_ID, MEMBER_ID
    ) T1
)T

SQLFiddle demo here

答案 1 :(得分:0)

我不太了解计算标准,但这样的事情应该有用......

SELECT team_id
     , member_id
     , COALESCE(MAX(CASE WHEN type = 'A' THEN score END),0) a_score
     , COALESCE(MAX(CASE WHEN type = 'B' THEN score END),0) b_score
     , COALESCE(MAX(CASE WHEN type = 'A' THEN score END),0) 
     - COALESCE(MAX(CASE WHEN type = 'B' THEN score END),0) diff
  FROM test2
 GROUP
    BY team_id
     , member_id;