ORACLE SQL排除Select中的结果(“字符串串联的结果太长)

dfty9e19  于 2023-11-17  发布在  Oracle
关注(0)|答案(1)|浏览(170)

在过去的几天里,我的头是旋转围绕这个问题,我真的希望你能帮助我与此.所以简化问题.这是我已经有表:
| ID|消息|时间|区|
| --|--|--|--|
| 1 |一|下午1| PT|
| 1 |B|下午1| PT|
| 1 |C|下午1| PT|
| 2 |D|凌晨2| FR|
| 2 |E|凌晨2| FR|
| 3 |F|下午3| TK|
我需要以下输出:
| ID|消息|时间|区|
| --|--|--|--|
| 2 |D、E|凌晨2| FR|
| 3 |F|下午3| TK|
我想串联在同一字段中相同ID的所有消息,我试图这样做,但由于某些ID的消息(示例ID 1)太大,检索ORA-01489“字符串连接的结果太长”。发生这种情况是因为我有数百行相同的ID,连接它们将超过4000个字符,所以我想从select中排除所有大于或等于3行的相同ID的计数,这样就不会处理并且不会检索到错误。
现在,过于简化的代码是沿着行的:

Select distinct id,
    LISTAGG(CASE when MESSAGE = ‘X’ THEN ‘Z’
    ELSE MESSAGE),
    TIME,
    ZONE
    FROM TABLE

字符串
添加一个where子句对解决这个问题没有帮助,我认为(但实际上我有点迷失在这里)解决方案必须在select中。
已经尝试过选择子句,但没有工作,已经尝试过修剪,但这不是视觉上的,这是处理能力的问题,所以它也没有做任何事情。

cyvaqqii

cyvaqqii1#

您可以使用分析查询来获取每个ID的行数:

select id, message, time, zone, count(*) over (partition by id) as cnt
from your_table

字符串
| ID|消息|时间|区|CNT|
| --|--|--|--|--|
| 1 |一|下午1| PT| 3 |
| 1 |B|下午1| PT| 3 |
| 1 |C|下午1| PT| 3 |
| 2 |D|下午2| FR| 2 |
| 2 |E|下午2| FR| 2 |
| 3 |F|下午3| TK| 1 |
然后你可以把它作为一个子查询,排除那些计数比你想要的高的查询:

select id,
  listagg(case when message = 'X' then 'Z' else message end, ',')
    within group (order by message) as messages,
  time,
  zone
from (
  select id, message, time, zone, count(*) over (partition by id) as cnt
  from your_table
)
where cnt < 3
group by id, time, zone
order by id, time, zone;


| ID|消息|时间|区|
| --|--|--|--|
| 2 |D、E|下午2| FR|
| 3 |F|下午3| TK|
fiddle
在您的数据中,每个ID的时间和区域值都是相同的。如果它们实际上不同,那么您也可以聚合它们,单独或组合-fiddle。或者,如果“time”实际上是一个日期/时间戳,您可以将它们组合为带有时区的时间戳,然后聚合它们。您可能还希望以与消息相同的顺序聚合它们;或聚合不同的值.取决于您如何使用输出。
您还可以获得消息长度(或者更确切地说,字节长度,以允许多字节字符)的分析总和,并使用该总和加上计数来查看它是否会超过聚合限制,以允许更多更短的消息。
正如我在评论中提到的,您可以在最近的版本中使用on overflow truncate子句-尽管您已经说过这不适合您正在做的事情。

相关问题