尝试通过选择多个值中的一个来聚合字符串列

时间:2016-09-08 20:11:55

标签: sql oracle

我有一个我想基于字符串列聚合的数据集。数据集基本上是:

system      status
-------------------
PRE1-SYS1   SUCCESS
PRE1-SYS2   SUCCESS
PRE2-SYS1   RUNNING
PRE2-SYS2   SUCCESS
PRE3-SYS1   SUCCESS
PRE3-SYS2   <blank>

基本上,我希望这成为:

system      status
-------------------
PRE1    SUCCESS
PRE2    RUNNING
PRE3    RUNNING

我有需要将系统值减少到PRE1和PRE2的sql,但是我不确定如何聚合字符串函数以便系统是:

  • 仅成功,然后状态为SUCCESS
  • 仅为空,然后状态为PENDING
  • 任何其他组合,然后RUNNING(SUCCESS / RUNNING,SUCCESS / null,RUNNING / null)

我看过LISTAGG,但我认为不适用。

4 个答案:

答案 0 :(得分:2)

以下是您可以使用的SQL查询:

select   regexp_substr(system, '^[^-]*') as prefix,
         case
            when count(status) = 0 then 'PENDING'
            when count(*) = count(case when status = 'SUCCESS' then 1 end) then 'SUCCESS'
            else 'RUNNING'
         end as status
from     mytable
group by regexp_substr(system, '^[^-]*')

答案 1 :(得分:2)

with
     inputs ( system, status ) as (
       select 'PRE1-SYS1', 'SUCCESS' from dual union all
       select 'PRE1-SYS2', 'SUCCESS' from dual union all
       select 'PRE2-SYS1', 'RUNNING' from dual union all
       select 'PRE2-SYS2', 'SUCCESS' from dual union all
       select 'PRE3-SYS1', 'SUCCESS' from dual union all
       select 'PRE3-SYS2',  ''       from dual
     ),
     prep ( system, flag ) as (
       select substr(system, 1, instr(system, '-') - 1),
              case status when 'SUCCESS' then 0 
                          when 'RUNNING' then 1 else 2 end
       from   inputs
     )
select system,
       case when min(flag) = 2 then 'PENDING'
            when max(flag) = 0 then 'SUCCESS'
            else                    'RUNNING' end as status
from prep
group by system
order by system;

<强>输出

SYSTEM    STATUS
--------- -------
PRE1      SUCCESS
PRE2      RUNNING
PRE3      RUNNING

答案 2 :(得分:0)

我会通过对回复进行排名来接近它。例如,将值设置为最不希望的结果所需的值:

SUCCESS = 1
RUNNING = 2
<blank> = 3
PENDING = 3 

然后根据它选择一个min。

select xval = case status when 'Success' then 1
                          when 'Running' then 2
                          when 'Pending' then 3
                                         else 3
                          end 

对您在此处获得的值使用嵌套的子选择,这样您每个系统只能获得一条记录。     选择系统,最小(Xval)

then display the 1 as Success
             the 2 as Running
             and 3 as Pending

用文本格式很难做到,更容易用数字做。您为字符串分配的数字很重要,因为它们决定了您在最终查询中返回的单个值的多个值。

答案 3 :(得分:0)

另一种选择。实际上,这最终与@ trincot的解决方案非常相似,我只是将逻辑从解释这些计数的逻辑中分离出来。如果您的逻辑在未来变得更加复杂,那么这可能会更灵活。

with
     inputs ( system, status ) as (
       select 'PRE1-SYS1', 'SUCCESS' from dual union all
       select 'PRE1-SYS2', 'SUCCESS' from dual union all
       select 'PRE2-SYS1', 'RUNNING' from dual union all
       select 'PRE2-SYS2', 'SUCCESS' from dual union all
       select 'PRE3-SYS1', 'SUCCESS' from dual union all
       select 'PRE3-SYS2',  ''       from dual
     ),
     /* The cnts CTE counts how many rows relate to a SYSTEM, 
        how many of those are SUCCESS, and how many are NULL.
      */
     cnts( system, num_rows, num_success, num_null ) as (
       select substr(system,1,instr(system, '-')-1) system,
              count(*),
              sum(case when status = 'SUCCESS' then 1 else 0 end),
              sum(case when status is null then 1 else 0 end)
        from inputs
       group by substr(system,1,instr(system, '-')-1)
     )
/* Using the counts from the CTE, we can implement whatever logic we
   want
 */
select system,
       (case when num_rows = num_success then 'SUCCESS'
             when num_rows = num_null then 'PENDING'
             else 'RUNNING'
         end) status
  from cnts