单行子查询返回多于一行。查询不适用于主查询

Rit*_*esh 0 sql subquery oracle-sqldeveloper

我必须在一个单元格中显示多个单元格值。所以我使用这个查询:

select LISTAGG(fc.DESCRIPTION,  ';'||chr(10))WITHIN GROUP (ORDER BY fc.SWITCH_NAME) AS DESCRIP from "ORS".SWITCH_OPERATIONS fc
       group by fc.SWITCH_NAME
Run Code Online (Sandbox Code Playgroud)

它工作正常。但是当我将它与我的主(完整)查询合并时,我得到的错误是:错误代码 1427,SQL 状态 21000:ORA-01427:单行子查询返回多于一行

这是我的完整查询:

SELECT
     TRACK_EVENT.LOCATION,
     TRACK_EVENT.ELEMENT_NAME,
     (select COUNT(*) from ORS.TRACK_EVENT b where (b.ELEMENT_NAME = sw.SWITCH_NAME)AND (b.ELEMENT_TYPE = 'SWITCH')AND (b.EVENT_TYPE = 'I')AND (b.ELEMENT_STATE = 'NORMAL' OR b.ELEMENT_STATE = 'REVERSE'))as COUNTER,
     (select COUNT(*) from ORS.SWITCH_OPERATIONS fc where TRACK_EVENT.ELEMENT_NAME = fc.SWITCH_NAME and fc.NO_CORRESPONDENCE = 1 )as FAIL_COUNT,
     (select MAX(cw.COMMAND_TIME) from ORS.SWITCH_OPERATIONS cw where ((TRACK_EVENT.ELEMENT_NAME = cw.SWITCH_NAME) and (cw.NO_CORRESPONDENCE = 1)) group by cw.SWITCH_NAME ) as FAILURE_DATE,
     (select LISTAGG(fc.DESCRIPTION,  ';'||chr(10))WITHIN GROUP (ORDER BY fc.SWITCH_NAME) AS DESCRIP from "ORS".SWITCH_OPERATIONS fc
       group by fc.SWITCH_NAME)

FROM
    ORS.SWITCH_OPERATIONS sw,
    ORS.TRACK_EVENT TRACK_EVENT
WHERE
    sw.SEQUENCE_ID = TRACK_EVENT.SEQUENCE_ID
Run Code Online (Sandbox Code Playgroud)

Clo*_*use 5

不仅是在子查询SELECT列表需要返回一列(或他们使用一个单一的比较,就像任何时间<=等),但他们在这方面的使用往往使数据库中执行他们RBAR-行逐痛苦的行。也就是说,它们比应有的速度更慢,消耗的资源更多。

通常,除非子查询外的结果集仅包含几行,否则您希望将子查询构造为表引用的一部分。即,类似于:

SELECT m.n, m.z, aliasForSomeTable.a, aliasForSomeTabe.bSum
FROM mainTable m
JOIN (SELECT a, SUM(b) AS bSum
      FROM someTable
      GROUP BY a) aliasForSomeTable
  ON aliasForSomeTable.a = m.a
Run Code Online (Sandbox Code Playgroud)

这在其他方面使您受益 - 例如,从同一个表引用中获取多个列更容易。

假设LISTAGG(...)可以包含在其他聚合函数中,您可以将查询更改为如下所示:

SELECT Track_Event.location, Track_Event.element_name, 
       Counted_Events.counter,
       Failure.fail_count, Failure.failure_date, Failure.descrip
FROM ORS.Track_Event
JOIN ORS.Switch_Operations
  ON Switch_Operations.sequence_id = Track_Event.sequence_id
LEFT JOIN (SELECT element_name, COUNT(*) AS counter
           FROM ORS.Track_Event
           WHERE element_type = 'SWITCH'
                 AND event_type = 'I'
                 AND element_state IN ('NORMAL', 'REVERSE') 
           GROUP BY element_name) Counted_Events
       ON Counted_Events.element_name = Switch_Operations.swicth_name 
LEFT JOIN (SELECT switch_name,
                  COUNT(CASE WHEN no_correspondence = 1 THEN '1' END) AS fail_count,
                  MAX(CASE WHEN no_correspondence = 1 THEN command_time END) AS failure_date,
                  LISTAGG(description,  ';' || CHAR(10)) WITHIN GROUP (ORDER BY command_time) AS descrip
           FROM ORS.Switch_Operations
           GROUP BY switch_name) Failure
       ON Failure.switch_name = Track_Event.element_name  
Run Code Online (Sandbox Code Playgroud)

此查询被写入(试图)保留原始查询的语义。我不完全确定这就是您真正需要的,但是没有示例起始数据和所需的结果,我无法说出如何改进这一点。例如,我有点怀疑Switch_Operations外部查询中的需要,以及LISTAGG(...)在行 where 上运行的事实no_correspondence <> 1。我确实更改了 的顺序LISTAGG(...),因为原始列不会做任何事情(因为排序方式与分组相同),所以不会是一个稳定的排序。