【问题标题】:Count non-null values in columns grouped by row type value from another column计算按另一列中的行类型值分组的列中的非空值
【发布时间】:2014-07-30 19:50:59
【问题描述】:

我正在使用 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

有了这份报告,我们就可以说“嘿,表格 A 永远不会填充第 4 列”。

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

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 Fiddle: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 个组件...pivot(在您的情况下为 unpivot)是将列带入行的术语。从那里你需要做空值计数逻辑。
  • 你可以使用count(c1), count(c2),...它自动忽略空值

标签: sql oracle


【解决方案1】:

如果您知道表单类型,那么您可以使用聚合查询来做到这一点:

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;

【讨论】:

  • 在第一个代码 sn-p 中,请将“from table t1”更改为“from t1”,然后它运行良好。在第二个 sn-p 中,请在第二个选择之后和第二个“union all”之前添加“from t1”,第三个和第四个选择同上,那么效果也很好。 :) 谢谢戈登·林诺夫。
【解决方案2】:
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 列编写它,但我想我会编写一个查询来为我写出来。

【讨论】:

  • 你还记得NULL等于NULL吗?
  • 这忽略了我关于使用“ftype”列中的值按表单类型分隔的问题
  • @chrislott 这样更好吗?
猜你喜欢
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
  • 2020-06-05
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
相关资源
最近更新 更多