单行子查询返回的行多于1-寻找解释/解决方案

时间:2019-04-03 18:27:51

标签: sql oracle sql-update subquery case

在这里长篇文章...振作起来...

我创建了以下4个查询,这些查询每天都按顺序运行。创建这些文件是为了使我的公司能够扫描工具进出服务状态,而不必手动输入日期。如图所示,调度无法调度使用该工具的作业。只要一个字段为空(SERVICE_DATE_IN),这些就可以正常工作并且没有任何问题:

查询1:扫描出工具

UPDATE PMEQMT P
   SET SERVICE_DATE_OUT = (SELECT MAX(TL.TRANS_DATE)
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND
                              TL.LOC_DESC = 'E-OUT OF SERVICE' AND
                              TL.TRANS_DATE >= SYSDATE - 1 AND
                              TL.TRANS_IN_OUT = 'IN'
                       )
WHERE P.CLASS = 'TL' AND
      P.SERVICE_DATE_OUT IS NULL

查询2:扫描到的工具

UPDATE PMEQMT P
   SET SERVICE_DATE_IN = (SELECT MAX(TL.TRANS_DATE)
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND 
                              TL.LOC_DESC = 'E-IN SERVICE' AND
                              TL.TRANS_DATE >= SYSDATE - 1 AND
                              TL.TRANS_IN_OUT = 'IN'
                       )
WHERE P.CLASS = 'TL' AND
      P.SERVICE_DATE_IN IS NULL

查询3:清除未清除的服务日期

UPDATE PMEQMT
SET SERVICE_DATE_IN = NULL
WHERE SERVICE_DATE_OUT IS NULL AND
  SERVICE_DATE_IN IS NOT NULL AND
  CLASS = 'TL'

查询4:工具又回来了,出/入日期均为空

UPDATE PMEQMT
SET SERVICE_DATE_OUT = NULL,
SERVICE_DATE_IN = NULL 
WHERE SERVICE_DATE_OUT IS NOT NULL AND
  SERVICE_DATE_IN IS NOT NULL AND
  CLASS = 'TL'

工程部已请求能够手动输入SERVICE_DATE_IN日期。因此,我提出了以下查询:

查询1:与上面的查询1相同

查询2:这是我的问题查询。目前,我收到错误消息:

  

ORA-01427:单行子查询返回多个行

在我进行测试并且仅将一个P.EQNO(项目)移动到TL.LOC_DESC(位置)时,此查询有效。然后,我开始测试将其他P.EQNO(项目)移动到不同的位置,然后开始接收错误。

有人能解释这里发生的事情吗?如果您感觉特别好,请帮助我修改查询以解决错误?

UPDATE PMEQMT P
   SET SERVICE_DATE_IN =
   CASE 
   WHEN SERVICE_DATE_IN IS NULL THEN (SELECT MAX(TL.TRANS_DATE)
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND 
                              TL.LOC_DESC = 'E-IN SERVICE' AND
                              TL.TRANS_DATE >= SYSDATE - 1 AND
                              TL.TRANS_IN_OUT = 'IN'
                       )
   WHEN (TRUNC(SERVICE_DATE_IN)) <= (TRUNC(SYSDATE)) THEN (SELECT ((TRUNC(SYSDATE))+1)
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND
                        TL.LOC_DESC = 'E-OUT OF SERVICE'
                       )
   WHEN (TRUNC(SERVICE_DATE_IN)) > (TRUNC(SYSDATE)) THEN (SELECT SERVICE_DATE_IN 
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND
                        TL.LOC_DESC = 'E-OUT OF SERVICE'
                       )
   END
WHERE CLASS = 'TL'

查询3:没有问题

UPDATE PMEQMT P 
SET P.SERVICE_DATE_OUT = NULL, P.SERVICE_DATE_IN = NULL 
WHERE EXISTS (SELECT 1 FROM TRANSLOG TL WHERE TL.ITEMNO = P.EQNO AND TL.LOC_DESC = 'E-IN SERVICE')

如果您发现我的代码有任何问题或有更好的方法,我会敞开心!!

--------------------编辑------------------------- < / p>

感谢@GMB,我有一个正确的工作查询。我现在遇到了两个相同的WHEN条件的问题。

UPDATE PMEQMT P 
SET SERVICE_DATE_IN = CASE 
WHEN SERVICE_DATE_IN IS NULL 
    THEN (
        SELECT MAX(TL.TRANS_DATE)
        FROM TRANSLOG TL
        WHERE 
            P.EQNO = TL.ITEMNO
            AND TL.LOC_DESC = 'E-IN SERVICE' 
            AND TL.TRANS_DATE >= SYSDATE - 1 
            AND TL.TRANS_IN_OUT = 'IN'
    )
WHEN 
    TRUNC(SERVICE_DATE_IN) <= TRUNC(SYSDATE) 
    AND EXISTS (        
        SELECT 1
        FROM TRANSLOG TL
        WHERE 
            P.EQNO = TL.ITEMNO 
            AND TL.LOC_DESC = 'E-OUT OF SERVICE'
    )
    THEN TRUNC(SYSDATE) +1        
WHEN TRUNC(SERVICE_DATE_IN) > TRUNC(SYSDATE) 
    THEN (
        SELECT MAX(SERVICE_DATE_IN)
        FROM TRANSLOG TL
        WHERE 
            P.EQNO = TL.ITEMNO
            AND TL.LOC_DESC = 'E-OUT OF SERVICE'
    )
WHEN TRUNC(SERVICE_DATE_IN) > TRUNC(SYSDATE)
    THEN (
          SELECT MAX(TL.TRANS_DATE)
          FROM TRANSLOG TL
          WHERE 
            P.EQNO = TL.ITEMNO
            AND TL.LOC_DESC = 'E-IN SERVICE' 
            AND TL.TRANS_DATE >= SYSDATE - 1 
            AND TL.TRANS_IN_OUT = 'IN'
    )
  END
WHERE CLASS = 'TL'

我正在测试的记录保留了MAX(SERVICE_DATE_IN)数据。我在这里有什么选择?我打算做一个嵌套的CASE,但是会遇到同样的问题。我可以做一个单独的查询,该查询在此查询之后运行,它完全看最后一组条件。我只是想知道是否可以在同一查询中执行。它实际上取决于TL.LOC_DESC值。

2 个答案:

答案 0 :(得分:1)

您需要某种逻辑将subuquery返回的记录数限制为一个。

在第一个子查询(这是您的第一个版本的查询的一部分)中,这是通过使用不带GROUP BY子句的聚合来提供的:

SET SERVICE_DATE_IN = (
    SELECT MAX(TL.TRANS_DATE)
    FROM TRANSLOG TL
    WHERE 
        P.EQNO = TL.ITEMNO
        AND TL.LOC_DESC = 'E-IN SERVICE'
        AND TL.TRANS_DATE >= SYSDATE - 1
        AND TL.TRANS_IN_OUT = 'IN'
)

返回值基本上为TRUNC(SYSDATE) +1的第二个子查询可以在NOT EXISTS语句的相关WHEN部分内移至CASE条件。

可以使用聚合来固定第三个子查询。

考虑:

UPDATE PMEQMT P 
SET SERVICE_DATE_IN = CASE 
    WHEN SERVICE_DATE_IN IS NULL 
        THEN (
            SELECT MAX(TL.TRANS_DATE)
            FROM TRANSLOG TL
            WHERE 
                P.EQNO = TL.ITEMNO
                AND TL.LOC_DESC = 'E-IN SERVICE' 
                AND TL.TRANS_DATE >= SYSDATE - 1 
                AND TL.TRANS_IN_OUT = 'IN'
        )
    WHEN 
        TRUNC(SERVICE_DATE_IN) <= TRUNC(SYSDATE) 
        AND EXISTS (        
            SELECT 1
            FROM TRANSLOG TL
            WHERE 
                P.EQNO = TL.ITEMNO 
                AND TL.LOC_DESC = 'E-OUT OF SERVICE'
        )
        THEN TRUNC(SYSDATE) +1        
    WHEN TRUNC(SERVICE_DATE_IN) > TRUNC(SYSDATE 
        THEN (
            SELECT MAX(SERVICE_DATE_IN)
            FROM TRANSLOG TL
            WHERE 
                P.EQNO = TL.ITEMNO
                AND TL.LOC_DESC = 'E-OUT OF SERVICE'
        )
   END
WHERE CLASS = 'TL'

答案 1 :(得分:0)

问题查询中的最后一种情况(如下所示)是否返回多行?不应该这样如果此行返回多个行,则查询将失败。

SELECT SERVICE_DATE_IN 
                        FROM TRANSLOG TL
                        WHERE P.EQNO = TL.ITEMNO AND
                        TL.LOC_DESC = 'E-OUT OF SERVICE'