Oracle 8i SQL - 连接不同行的字符串

时间:2017-01-14 04:58:15

标签: sql string oracle concatenation oracle8i

我需要连接不同行的字符串,如下所示 每个NAME的行数是可变的,其范围是未知的。

NAME  COLOR
Bob   Red
Bob   Blue
Tom   Green
John  Red
John  Yellow
John  Purple

期望的输出:

NAME  COLORS
Bob   RedBlue
Tom   Green
John  RedYellowPurple

我面临的局限是:

  • Oracle 8i(8.1.7.4.0) - 我对此无法控制,升级是 不是一个选择
  • 只读访问
  • 无法创建......

基本上是这样的:

  • no CREATE
  • 没有LISTAGG
  • 没有XMLAGG
  • 没有WM_CONCAT
  • 没有参考光标
  • 没有SYS_CONNECT_BY_PATH

我是SOL吗?

1 个答案:

答案 0 :(得分:0)

Oracle 8i至少支持分析功能,因此您可以使用row_number()dense_rank()为每个颜色值指定一个名义数字(按照您的意义排序):

select name, color,
  row_number() over (partition by name order by color) as rn
from your_table;

然后使用手动数据透视的变体,每个可能的行号有一个max(decode())

select name,
  max(decode(rn, 1, color))
  || max(decode(rn, 2, color))
  || max(decode(rn, 3, color))
  || max(decode(rn, 4, color))
  || max(decode(rn, 5, color))
  || max(decode(rn, 6, color))
  || max(decode(rn, 7, color))
  -- ...
  as colors
from (
  select name, color,
    row_number() over (partition by name order by color) as rn
  from your_table
)
group by name
order by name;

NAME       COLORS                                                                
---------- ----------------------------------------------------------------------
Bob        BlueRed                                                               
John       PurpleRedYellow                                                       
Tom        Green                                                                 

您说范围未知,但即使每个名称的行数不限,您仍然受到最终连接字符串限制,最多不得超过4000个字符 - 根据您对实际情况的了解颜色值可以为您提供最大可用数量。 (并且您可以自动生成解码部分作为一次性事物)。

如果需要,您可以使用相同的方式包含分隔符:

select name,
  max(decode(rn, 1, color))
  || max(decode(rn, 2, ',')) || max(decode(rn, 2, color))
  || max(decode(rn, 3, ',')) || max(decode(rn, 3, color))
  || max(decode(rn, 4, ',')) || max(decode(rn, 4, color))
  || max(decode(rn, 5, ',')) || max(decode(rn, 5, color))
  || max(decode(rn, 6, ',')) || max(decode(rn, 6, color))
  || max(decode(rn, 7, ',')) || max(decode(rn, 7, color))
  || max(decode(rn, 8, ',')) || max(decode(rn, 8, color))
  -- ...
  as colors
from (
  select name, color,
    row_number() over (partition by name order by color) as rn
  from your_table
  where color is not null
)
group by name
order by name;

NAME       COLORS                                                                                 
---------- ---------------------------------------------------------------------------------------
Bob        Blue,Red                                                                               
John       Purple,Red,Yellow                                                                      
Tom        Green                                                                                  

我在内部查询中包含一个is not null过滤器,以防该列可以为空 - 这应该阻止最终列表中的空元素。

(未在8i中进行测试,因为我无法找到一个旧的旋转实例,但我不认为这是使用后来介绍的任何内容......)