【问题标题】:UNPIVOT issue between two similar queries两个类似查询之间的 UNPIVOT 问题
【发布时间】:2017-04-28 20:42:30
【问题描述】:

尝试在 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”:无效标识符 00904. 00000 - “%s:无效标识符” *原因:
*行动: 行错误:1,685 列:50

有人可以帮忙找出原因吗?

【问题讨论】:

  • 输出应该是什么样子的?还有多少列 a,b,c,d 你有?修好了吗?
  • 两个发布的例子都产生同样的错误online fiddle:

标签: sql oracle unpivot


【解决方案1】:

有问题的查询是不同的。

1) 在第一个查询中,您首先计算各个列中非null 的数量,然后unpivoting 它们。

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

【讨论】:

  • In the second, you are unpivoting first, and trying to count them. 这有帮助。
【解决方案2】:
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

【讨论】:

  • @MTO 感谢您分解它以解释我的第二个查询失败的原因。
【解决方案3】:

显然,鉴于您编写的 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 对所有未用双引号括起来的列名所做的相同)。

【讨论】:

  • values to check are 'A', 'B', 'C' and 'D', not the lower-case versions。感谢您提供更详细的信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
相关资源
最近更新 更多