单行子查询返回多行。查询不使用主查询

时间:2014-07-10 16:45:27

标签: 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

工作正常。但是当我将其与我的主(完整)查询合并时,我得到的错误为:错误代码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

2 个答案:

答案 0 :(得分:3)

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

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

假设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  

此查询被写入(尝试)保留原始查询的语义。我不完全确定你实际需要,但没有样本开始数据和期望的结果,我无法告诉你如何改进它。例如,我有点怀疑外部查询中Switch_Operations的需要,以及LISTAGG(...)no_correspondence <> 1的行上运行的事实。我确实更改了LISTAGG(...)的顺序,因为原始列不会做任何事情(因为订单方式与分组相同),所以不会是稳定的排序。

答案 1 :(得分:1)

单行子查询返回多行。
此错误消息是自描述的 返回的字段不能有多个值,子查询返回多行 在完整查询中,指定要返回的字段。最后一个字段需要来自子查询的单个值,而是获得多个行。

我对你正在使用的数据一无所知,但要么你必须确保子查询只返回一行,要么你必须重新设计包装查询(可能在适当的时候使用连接)。