zoukankan      html  css  js  c++  java
  • TSQL 行列互换

    对于一个简单的表, 两行两列(行号暂且不算). 要对它进行行列互换, 怎么做?

    先准备测试数据:

    CREATE TABLE TempSum(
        n INT,
        gender VARCHAR(10),
        total INT
    );
    
    INSERT INTO TempSum(n, gender, total) VALUES
    (1, 'male', 23), (2, 'female', 45);
    
    SELECT * FROM TempSum;
    n gender total
    ---- ------ ----- 1 male 23 2 female 45

    看到行列互换, 大家首先想到的大概是PIVOT:

    SELECT n, male, female
    FROM TempSum
    pivot(max(total) FOR gender
        IN (male, female)) AS P;
    
    n    male female
    ---- ---- ------
       1   23   NULL
       2 NULL     45

    或者, n列也可以去掉的:

    SELECT
        -- n, --uncomment to show n
        max(CASE WHEN gender='male' THEN total END) AS male,
        max(CASE WHEN gender='female' THEN total END) AS female
    FROM TempSum
    GROUP BY n;
    
    male female
    ---- ------
      23   NULL
    NULL     45

    如果, 我不想要NULL, 要显示成

    male female
    23   45    

    的样式. 或者, 如果TempSum表中根本没有n列. 怎么办?

    思路:

    Step1, 把male和female放到一行

    Step2, 把23和45放到一行, 要注意它们和gender的对应顺序

    Step3, 把Step1和Step2的两行作个UNION. OK!

    实现:

    Step1, gender可以认为是已知的, hard code就可以的:

    SELECT 'male', 'female' 

    Step2, male和female的total本不在同一行, 可以做个自连接, 选出来一行让它左边对应male的total, 右边对应female的total:

    SELECT convert(VARCHAR(10), a.total), convert(VARCHAR(10), b.total)
    FROM TempSum a JOIN TempSum b ON a.gender<>b.gender
    WHERE a.gender='male' --AND b.gender='female'

    Step3, 用UNION ALL就可以的, 就不多解释了:

    SELECT 'male', 'female' 
    UNION ALL
    SELECT convert(VARCHAR(10), a.total), convert(VARCHAR(10), b.total)
    FROM TempSum a JOIN TempSum b ON a.gender<>b.gender
    WHERE a.gender='male' --AND b.gender='female';
    
    -- results
    No Column Name No Column Name
    -------------- --------------
    male           female        
    23             45            

    看到No Column Name, 把它也去掉吧. 其实, 走到Step2的时候, 大概就可以想到了:

    SELECT convert(VARCHAR(10), a.total) AS male, convert(VARCHAR(10), b.total) AS female
    FROM TempSum a JOIN TempSum b ON a.gender<>b.gender
    WHERE a.gender='male'
    
    -- results
    male female
    ---- ------
    23   45    

    到这里, 我们已经抛弃了最初提到的n列, 屏蔽了NULL. 我们可以把列名gender、total加回来:

    SELECT 'total' AS gender, convert(VARCHAR(10), a.total) AS male, convert(VARCHAR(10), b.total) AS female
    FROM TempSum a JOIN TempSum b ON a.gender<>b.gender
    WHERE a.gender='male'

    最终, 我们从

    gender total
    ------ -----
    male      23
    female    45

    得到了

    gender male female
    ------ ---- ------
    total  23   45    
    本文系☆大森林☆创作于博客园, 转载请保留此说明
    更多请访问 freeway.cnblogs.com
  • 相关阅读:
    旅行,写作,编程
    Limu:JavaScript的那些书
    怎样花两年时间去面试一个人
    IE6之各种不适记录
    19位编程大师集锦
    开源中最好的Web开发资源汇总
    流行Linux和Windows脚本语言列表
    近来,一组名为“全球郁闷青年写真”的照片在网上热传...
    浏览器端技术体系概览 前端开发的七种武器
    这个世界从来没有任何一件工作叫“钱多、事少、离家近”
  • 原文地址:https://www.cnblogs.com/Freeway/p/2962396.html
Copyright © 2011-2022 走看看