计算按另一列的行类型值分组的列中的非空值

时间:2014-07-30 19:50:59

标签: sql oracle

我正在使用Oracle数据库,尝试计算列中的非空值并按行类型报告结果。请帮助,我经常因SQL的力量而感到谦卑。

我有一份财务报表表单数据表:第1列是表单类型,列2..900(严重来说非常宽)具有空值或数字。所以我试图通过表单类型来表征非空值。

表t1的示例片段 - 仅显示2但有8种表单类型:

ftype   c1     c2     c3     c4      c5
-----   --     --     --     --      --
a       1      2      3      null    null 
b       null   null   null   4       5
b       null   null   null   44      55

所需报告如下;数字是上面样本表中的非空计数:

        a      b
        --     --
c1      1      0
c2      1      0
c3      1      0
c4      0      2
c5      0      2

通过此报告,我们可以说"嘿,第4列永远不会填写表格A"。

如果我用程序编程语言解决问题,我会写下面的内容。然后我将结果作为一个大表发出:

for FORM in FormA .. FormH
    for COLUMN in Col1 .. Col900
        select count(*) from t1 where ftype = '${FORM}' and ${COLUMN} is not null;
    end for
end for

SO的这些帖子向我指出CASE结构,但不完全相同:

Count number of NULL values in each column in SQL

Counting non-null columns in a rather strange way

我还为这个问题创建了一个SQL小提琴:http://sqlfiddle.com/#!2/e4d43/2

聪明的方式是什么?我是否必须编写大量SQL查询?提前谢谢。

更新1:感谢您的快速回复。我只需要这些信息,如果报告中的列数和类型都不在乎,请不要关心,解决方案是否更容易(即不需要支点)?以下对我来说很好,它会变得非常广泛,但我们应对:

     c1    c2    c3    c4    c5
     --    --    --    --    --
 a    1     1     1     0     0
 b    0     0     0     2     2

2 个答案:

答案 0 :(得分:0)

SELECT ftype, sum(case when c1 is null then 0 else 1) C1Used,
   sum(case when c2 is null then 0 else 1) C2Used,
   sum(....
FROM Form
Group by ftype;

就是我这样做的方式。这将给你一个计数,零将是"不使用"将它写成900列,我想我会编写一个查询来为我写出来。

答案 1 :(得分:0)

如果您知道表单类型,则可以使用聚合查询执行此操作:

select ftype,
       count(c1) as c1,
       count(c2) as c2,
       count(c3) as c3,
       count(c4) as c4
from t1
group by ftype;

请注意count(<expression>)计算<expression>中的非NULL值。这是最简单的结果。如果您希望为每个列获取单独的行,并为每个ftype获取单独的列,则查询会更加麻烦。这是一种方式:

select 'c1' as col,
       sum(case when ftype = 'a' and c1 is not null then 1 else 0 end) as a,
       sum(case when ftype = 'b' and c1 is not null then 1 else 0 end) as b
from table1
union all
select 'c2' as col,
       sum(case when ftype = 'a' and c2 is not null then 1 else 0 end) as a,
       sum(case when ftype = 'b' and c2 is not null then 1 else 0 end) as b
from table1
union all
select 'c3' as col,
       sum(case when ftype = 'a' and c3 is not null then 1 else 0 end) as a,
       sum(case when ftype = 'b' and c3 is not null then 1 else 0 end) as b
from table1
union all
select 'c4' as col,
       sum(case when ftype = 'a' and c4 is not null then 1 else 0 end) as a,
       sum(case when ftype = 'b' and c4 is not null then 1 else 0 end) as b
from table1;