【问题标题】:Sorting variables in a record对记录中的变量进行排序
【发布时间】:2013-09-27 01:31:56
【问题描述】:

我有一个包含多个列的 Oracle 表,其中一些列填充了一个变量,有大量可能的变量,下面的示例并不详尽。

ID  Col1  Col2  Col3 
--------------------
1   A     B
2   B     A     D
3   B     C
4   C     B     
5   B     B
6   E     D   
7   B     A     C

我需要创建一个查询每行中的变量:

ID  Col1  Col2  Col3 
--------------------
1   A     B
2   A     B     D
3   B     C
4   B     C     
5   B     B
6   D     E   
7   A     B     C

我正在寻找一个优雅的解决方案,因为现实世界的问题有 20 列,最多包含 40 个不同的变量(每列最多四个字符)和数百万条记录。

【问题讨论】:

  • 你试过什么?你有什么错误?给我们看一些代码。也在 sql 中标记这个
  • 我们如何知道要重新洗牌的列?它必须是查询还是存储过程?
  • 我还没有测试过这个解决方案,但是这个问题似乎在尝试做同样的事情:stackoverflow.com/questions/12100566/…
  • 没有“变量”的字段中有什么:spaceNULL
  • 哪些 cols 排序是个好问题 - 我应该说我认为必须指定它们,例如 col1, col2, col3 .. coln

标签: sql oracle sorting


【解决方案1】:

下面是Oracle 10g 及更高版本的变体。因为原始数据集中有大量行,所以我会尽量避免涉及在完整结果集之上进行分组和分析函数的解决方案。

此示例的基表:

create table tab1 (
  ID   number,
  col1 varchar2(4), 
  col2 varchar2(4), 
  col3 varchar2(4), 
  col4 varchar2(4) 
)

首先,将每个ID 的所有列收集到排序集合:

select
  tab1.ID,
  cast( multiset(
    select 
      decode(level,
        1, tab1.col1,
        2, tab1.col2,
        3, tab1.col3,
        4, tab1.col4,
        null
      )       
    from dual 
    connect by level <= 4
    order by 
      decode(level,
        1, tab1.col1,
        2, tab1.col2,
        3, tab1.col3,
        4, tab1.col4,
        null
      ) 
      nulls last          
  ) as sys.ODCIVarchar2List) sorted_values
from tab1;

拥有这样的数据集,可以在保持指定顺序的同时将值解码回列:

select
  ID,
  (
    select column_value 
    from table(data_list.sorted_values)
    where rownum = 1
  ) as col1,
  (
    select max(decode(rownum, 2, column_value, null))
    from table(data_list.sorted_values)
  ) as col2,
  (
    select max(decode(rownum, 3, column_value, null))
    from table(data_list.sorted_values)
  ) as col3,
  (
    select max(decode(rownum, 4, column_value, null))
    from table(data_list.sorted_values)
  ) as col4
from (
  select
    rownum,  -- this needed as workaround for Oracle bug
    tab1.ID,
    cast( multiset(
      select 
        decode(level,
          1, tab1.col1,
          2, tab1.col2,
          3, tab1.col3,
          4, tab1.col4,
          null
        )       
      from dual 
      connect by level <= 4
      order by 
        decode(level,
          1, tab1.col1,
          2, tab1.col2,
          3, tab1.col3,
          4, tab1.col4,
          null
        ) 
        nulls last          
    ) as sys.ODCIVarchar2List) sorted_values
  from tab1
) 
  data_list

SQLFiddle test

注意rownum 必须存在于内部select 子句中,作为this Oracle error 的解决方法。

【讨论】:

  • 哇,这是一个不错的解决方案。 SQLFiddle 版本是一种享受。我得到错误代码:907 ORA-00907:当我在 Oracle 11.2.0.2.0 的生产环境中运行它时缺少右括号有什么想法 - 代码看起来都很好......?
  • @user2798561 您尝试运行示例中的确切代码(例如通过复制和粘贴)或已经针对您的解决方案进行了调整?您是否真的在某个地方错过了正确的括号? SQL Fiddle 正好运行 11.2.0.2.0 (proof link)。
猜你喜欢
  • 2019-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 2013-04-28
  • 2018-04-29
  • 2013-07-17
  • 2022-01-18
相关资源
最近更新 更多