两个相似查询之间的 UNPIVOT 问题

UNPIVOT issue between two similar queries

正在尝试在 oracle 12c 中解决问题 (SQL: query to show how many users have each property (grouped))。

with data (id, name, a, b, c, d) as
(
  select 1, 'name1', 'yes', 'yes', '', 'yes' from dual union all
  select 2, 'name2', 'yes', '', '', 'yes' from dual union all
  select 3, 'name3', '', 'yes', '', 'yes' from dual union all
  select 4, 'name4', 'yes', 'yes', '', 'yes' from dual union all
  select 5, 'name5',  '', '', 'yes', 'yes' from dual 
)
,
coll (a,b,c,d) as
(
  select count(a) a, count(b) b, count(c) c, count(d) d from data
)
select * from coll
unpivot 
(
  val for (col) in (a, b, c, d)
);

工作正常并产生了预期的结果。

鉴于

with data (id, name, a, b, c, d) as
(
select 1, 'name1', 'yes', 'yes', '', 'yes' from dual union all
select 2, 'name2', 'yes', '', '', 'yes' from dual union all
select 3, 'name3', '', 'yes', '', 'yes' from dual union all
select 4, 'name4', 'yes', 'yes', '', 'yes' from dual union all
select 5, 'name5',  '', '', 'yes', 'yes' from dual 
)
--,
--coll (a,b,c,d) as
--(
select count(a) a, count(b) b, count(c) c, count(d) d from data -- Line 1685
--)
--select * from coll
unpivot 
(
val for (col) in (a, b, c, d)
);

产生以下错误。

ORA-00904: "D": invalid identifier 00904. 00000 - "%s: invalid identifier" *Cause:
*Action: Error at Line: 1,685 Column: 50

谁能帮忙看看为什么会这样?

with data (id, name, a, b, c, d) as (
  select 1, 'name1', 'yes', 'yes', '',    'yes' from dual union all
  select 2, 'name2', 'yes', '',    '',    'yes' from dual union all
  select 3, 'name3', '',    'yes', '',    'yes' from dual union all
  select 4, 'name4', 'yes', 'yes', '',    'yes' from dual union all
  select 5, 'name5',  '',   '',    'yes', 'yes' from dual 
)
select * from data
unpivot (  val for (col) in (a, b, c, d) );

输出

    ID NAME  COL VAL
------ ----- --- ---
     1 name1 A   yes
     1 name1 B   yes
     1 name1 D   yes
     2 name2 A   yes
     2 name2 D   yes
     3 name3 B   yes
     3 name3 D   yes
     4 name4 A   yes
     4 name4 B   yes
     4 name4 D   yes
     5 name5 C   yes
     5 name5 D   yes

输出中没有要计数的列 ABCD

如果您想获得相同的输出,您需要按 COL:

分组
with data (id, name, a, b, c, d) as (
  select 1, 'name1', 'yes', 'yes', '',    'yes' from dual union all
  select 2, 'name2', 'yes', '',    '',    'yes' from dual union all
  select 3, 'name3', '',    'yes', '',    'yes' from dual union all
  select 4, 'name4', 'yes', 'yes', '',    'yes' from dual union all
  select 5, 'name5',  '',   '',    'yes', 'yes' from dual 
)
select COL, COUNT(*) AS VAL from data
unpivot (  val for (col) in (a, b, c, d) )
GROUP BY col
ORDER BY col;

输出:

COL        VAL
--- ----------
A            3
B            3
C            1
D            5

有问题的查询是不同的。

1) 在第一个查询中,您最初计算了各个列中非 null 的数量,然后 unpivot 计算它们。

2) 在第二个中,您首先 unpivoting,然后尝试对它们进行计数。在 unpivot 之后没有 a、b、c、d 列。他们将在 col.. 正如你所说的 val for col in (a,b,c,d)。要获得与第一个相同的结果,请使用

select col,count(*) as val 
from data -- Line 1685
unpivot (
         val for col in (a,b,c,d)
        )
group by col

显然,鉴于您编写的 SELECT 子句,如果第二个查询完全有效,结果将全部在一行中,在标记为 A、B、C、D 的四列中。如果就是你想要的,那么你需要条件COUNT:

with data (id, name, a, b, c, d) as
(
select 1, 'name1', 'yes', 'yes', ''   , 'yes' from dual union all
select 2, 'name2', 'yes', ''   , ''   , 'yes' from dual union all
select 3, 'name3', ''   , 'yes', ''   , 'yes' from dual union all
select 4, 'name4', 'yes', 'yes', ''   , 'yes' from dual union all
select 5, 'name5',  ''  , ''   , 'yes', 'yes' from dual 
)
select count(case col when 'A' then 1 end) as a,
       count(case col when 'B' then 1 end) as b,
       count(case col when 'C' then 1 end) as c,
       count(case col when 'D' then 1 end) as d
from data
unpivot 
(
val for (col) in (a, b, c, d)
);

A  B  C  D
-  -  -  -
3  3  1  5

请注意,要检查的值是 'A'、'B'、'C' 和 'D',而不是小写版本。在 UNPIVOT 子句中,如果您不在 IN 子句中使用别名,则 COL 列中的值将只是 IN 子句中列的名称(a、b、c、d),始终大写(与 Oracle 对所有未包含在双引号中的列名所做的相同)。