透视未知字段值 [重复]

Pivot an unknown field value [duplicate]

提问人:emare 提问时间:10/20/2023 最后编辑:emare 更新时间:10/21/2023 访问量:61

问:

我正在运行 Oracle 11。 我有一个客户参考资料表,上面有要打印的文件。有很多类型的文件,我事先并不了解它们。shorto04

下面是一个数据示例:

短O04 wdocname
7739096 SL00A系列
7739096 TR00A系列
7740767 AV00BITA
7768159 SL00AFRA
7768159 TR00AFRA
7768159 AD00AFRA
7768159 PL00AFRA
7771629 SL00A系列
7780966 TR00A系列
7780966 AD00A型
7812187 SL00A系列
7812187 TR00A系列
7812187 AD00A型
7817697 SL00AGBR
7817697 TR00AGBR
7817697 AV00BGBR
7818401 SL00AGBR
7818401 TR00AGBR
7818412 SL00AGBR
7818412 TR00AGBR
7829375 SL00AGBR
7829375 TR00AGBR
7829375 PL00AGBR
7832296 SL00A系列
7832296 TR00A系列
7832296 AD00A型
7832297 SL00A系列
7832297 TR00A系列
7832297 AD00A型
7840205 OD00IGBR
7840205 SL00DGBR
7840205 AV00DGBR

老板要求计算所有不同的类型以及我们有多少。 所以我从一个像belolw这样的查询开始:

Select *
from 
(
select shorto04, SUBSTR(wdocname, 1,5) as docs
 from O04T91
)
pivot
(
count(docs)
for docs in ( 'TR00A' , 'OD00A')  
) 

当然,我的sql结果与我需要的相去甚远:

短O04 tr00a_ od00a_
7709902 1,000000 0,000000
7725337 1,000000 0,000000
7729012 1,000000 0,000000
7729062 1,000000 0,000000
7739096 1,000000 0,000000
7740767 1,000000 1,000000
7768159 1,000000 0,000000
7771629 1,000000 0,000000

使用我的方法,我需要在查询中对所有可能的文档类型进行硬编码,如果有任何新的文档类型,它们将不会被计算在内。

下面是部分预期结果的示例:

短O04 TR00A系列 OD00A型 AD00A系列 AV00B系列 SL00A系列 OD00i型 AV00D系列
7709902 1 0 1 0 1 0 0
7725337 1 0 1 0 1 0 0
7729012 1 0 0 1 1 0 0
7729062 1 0 0 1 1 0 0
7739096 1 0 1 0 1 0 0
7740767 1 1 0 1 0 0 0
7768159 1 0 1 0 1 0 0
7771629 1 0 1 0 1 0 0
7780966 1 0 1 0 1 0 0
7812187 1 0 1 0 1 0 0
7817697 1 0 0 1 1 0 0
7818401 1 0 0 0 1 0 0
7818412 1 0 0 0 1 0 0
7829375 1 0 0 0 1 0 0
7832296 1 0 1 0 1 0 0
7832297 1 0 1 0 1 0 0
7840205 0 0 0 0 0 1 1
7840228 1 1 1 0 1 0 0

任何帮助将不胜感激。 谢谢

SQL Oracle11g 透视表

评论

1赞 Alex Poole 10/20/2023
您必须使用动态 SQL,或在外部报告工具中透视;但这种输出真的有用吗?“计算所有不同类型以及我们有多少”的要求实际上意味着“对于每个 shorto04”,还是您真的只想要所有客户的总数?
0赞 emare 10/20/2023
这只是查询的核心,我正在添加客户名称等,因为他们要求相同类型的不同文档(即 3 种标签类型,而我们的政策只需要 1 种标签类型......等等)。这最终将对我们的客户采取行动。以 shorto04=7740767 为例,“tr”和“od”是两个标签,系统打印两个标签,工人只打印一个装订书钉,扔掉另一个标签。
1赞 Alex Poole 10/20/2023
好的,但是如果你有这个透视结果,你将无法用它做任何进一步的事情,如果没有更多的动态 SQL,因为外部查询也需要知道列名。我认为你可能需要重新考虑你的方法......

答:

1赞 Lajos Arpad 10/20/2023 #1

您可以通过以下方式选择不同的值

select distinct wdocname
from shorto04;

并生成如下所示的查询:

SELECT 
    'SELECT Shorto04, ' ||
    LISTAGG(
      '(SELECT COUNT(*) FROM ORDREF tmp  WHERE tmp.shorto04 = ORDREF.shorto04 and wdocname = ''' ||
      wdocname ||
      ''') AS ' ||
      wdocname ||
      ' FROM ORDREF GROUP BY Shorto04;'
    , ',') WITHIN GROUP(ORDER BY wdocname) AS query
FROM (
    SELECT DISTINCT wdocname
    FROM ORDREF
) t;

SELECT Shorto04,
       (SELECT COUNT(*) FROM ORDREF tmp WHERE tmp.shorto04 = ORDREF.shorto04 and wdocname = 'OD00A') AS OD00A,
       (SELECT COUNT(*) FROM ORDREF tmp WHERE tmp.shorto04 = ORDREF.shorto04 and wdocname = 'TR00A') AS TR00A
FROM ORDREF
GROUP BY Shorto04;

基本上,您添加主列,然后以逗号分隔的方式选择子列,将 distinct 作为输入。查询未经测试。如果您使用示例数据创建 SQL Fiddle,我很乐意对其进行更实际的测试。wdocname

编辑

由于提供了 SQL Fiddle,我能够在实践中测试查询,并且我已经调整了查询以在实践中工作。已经在上面更新了。

小提琴链接: http://www.sqlfiddle.com/#!4/cd7e3/1

第一个查询,即此答案中共享的查询,生成要作为文本实际执行的查询。Oracle 能够将文本作为查询执行,请参阅:Oracle SQL 查询能否执行从表中选择的字符串查询?

评论

0赞 emare 10/20/2023
这是我第一次尝试 SQL Fiddle sqlfiddle.com/#!9/72d450/1
0赞 MT0 10/20/2023
这看起来像未经测试的代码。如果你测试过它,你会发现缺少逗号,其他地方有太多的逗号,然后当你修复这些错误时,你会发现它只需要 2 个参数。CONCAT
0赞 Lajos Arpad 10/21/2023
@MT0它确实是未经测试的代码,正如我在答案中澄清的那样,因为没有输入可以处理。由于 Emare 已经发送了一把小提琴,我打算研究它并调整代码。
0赞 Lajos Arpad 10/21/2023
@emare谢谢你的小提琴。相应地修复了代码,请在答案和我给出的链接中查看。
0赞 Lajos Arpad 10/21/2023
@MT0编辑了我的答案,所以现在代码是正确的,因为我们现在有一个正确的输入。