SQL查询将列计数转换为行计数

时间:2014-09-11 22:18:13

标签: sql postgresql unpivot unnest

我有一个表格,如下所示,显示了类型的数量。我需要并且一直试图将数据显示为1列和7行而不是......但没有成功。

__________________________________________________________________________
| col types      | win2k | winxp | win2k3 | vista | win7 | win8 | win8.1 |
--------------------------------------------------------------------------
| count of types |  2365 | 65655 | 422445 | 4822  | 482  | 2331 | 485323 |
--------------------------------------------------------------------------
Select 
count(case when col1 ~* '5.0.2195' then 1 else null end) as Win2k,
count(case when col1 ~* '5.1.2600' then 1 else null end) as WinXP, 
count(case when col1 ~* '5.2.3790' then 1 else null end) as W2k3,
count(case when (col1 ~* '6.0.6000'
    or col1 ~* '6.0.6001' or col1 ~* '6.0.6002') 
    then 1 else null end) as Vista,
count(case when (col1 ~* '6.1.7600'
    or col1 ~* '6.1.7601')
    then 1 else null end) as Win7,
count(case when col1 ~* '6.2.9200' then 1 else null end) as Win8,
count(case when (col1 ~* '6.3.9200'
    or col1 ~* '6.3.9600')
    then 1 else null end) as "Win8.1"
From col1

理想情况下,它看起来像这样:

___________________
| types  | count  |
-------------------
| win2k  | 2365   |
| winxp  | 65655  |
| win2k3 | 422445 | 
| vista  | 4822   |
| win7   | 482    |
| win8   | 2331   |
| win8.1 | 485323 |
-------------------

注意:

  • 我正在使用Postgresql 9.3和PGADMIN III
  • 我无法创建任何自定义函数
  • 如果有更多列可以使这项工作无关紧要

3 个答案:

答案 0 :(得分:0)

我喜欢使用Postgres特定的并行unnest()

SELECT unnest('{win2k,winxp,win2k3,vista,win7,win8,win8.1}'::text[]) AS type
      ,unnest(ARRAY[
          count(some_column ~ '5.0.2195' OR NULL)
         ,count(some_column ~ '5.1.2600' OR NULL)
          .. the rest from your query above ...
       ]) AS ct
FROM   profile.foo

两个数组中的值和序列号必须匹配 相关答案以及更多细节(请务必阅读!):

替代计数技术(可选)

count()仅计算非空值..

(TRUE  OR NULL) IS TRUE  
(FALSE OR NULL) IS NULL  
(NULL  OR NULL) IS NULL

VOILÀ。仅计算TRUEMore details in this answer on dba.SE.

除此之外:在表达式中使用~ instead of ~*,因为这些字符串文字中没有区分大小写的字母。但我怀疑你需要一个正则表达式匹配。

此外,列名profile.foo没有意义,因为唯一的表名为foo,而不是profile

答案 1 :(得分:0)

这些类型的查询更容易以GROUP BY为目标,如下所示:

Select 
case when profile.foo ~* '5.0.2195' then 'Win2k'
     when profile.foo ~* '5.1.2600' then 'WinXP' 
     when profile.foo ~* '5.2.3790' then 'W2k3'
     when (profile.foo ~* '6.0.6000'
        or profile.foo ~* '6.0.6001'
        or profile.foo ~* '6.0.6002') 
        then 'Vista'
     when (profile.foo ~* '6.1.7600'
        or profile.foo ~* '6.1.7601')
        then 'Win7'
     when profile.foo ~* '6.2.9200' then 'Win8'
     when (profile.foo ~* '6.3.9200'
        or profile.foo ~* '6.3.9600')
        then 'Win8.1' ELSE 'Other' END as type,
     count(*) as cnt
From profile
GROUP BY 1

如下所述,此查询适用于互斥的情况,即当profile.foo包含表示每行一个操作系统的值时

答案 2 :(得分:0)

不要使用条件聚合,只需使用CASE正确填充Type,然后在Type上分组:

   ;with cte AS (Select   case when profile.foo ~* '5.0.2195' then 'Win2k'
                               when profile.foo ~* '5.1.2600' then 'WinXP' 
                               when profile.foo ~* '5.2.3790' then 'W2k3'
                               when profile.foo ~* '6.0.6000' or profile.foo ~* '6.0.6001' or profile.foo ~* '6.0.6002' then 'Vista'
                               when (profile.foo ~* '6.1.7600' or profile.foo ~* '6.1.7601') then 'Win7'
                               when profile.foo ~* '6.2.9200' then 'Win8'
                               when (profile.foo ~* '6.3.9200' or profile.foo ~* '6.3.9600') then 'Win8.1'
                          end as Type
                 From profile.foo)
    SELECT Type,COUNT(*) AS ct
    FROM cte
    GROUP BY Type

对于postgresql语法不是100%,但逻辑是兼容的。