我目前有一个CASE语句,用于检查某些任务是否已完成,然后返回下一个任务的日期。由于任务是有序的,因此每个WHEN语句变得更长,检查先前的每个任务以查看它们是否完整。出于某种原因,在第一个WHEN声明之后,它直接跳到ELSE(它应该满足第二个或第三个WHEN的条件)。
CASE
WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1)
WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2) THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1)
WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2) THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1)
ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1)
END
您需要一种特定的方式来解决这些类型的多个WHEN条件吗?
编辑:所以在你们的一些反馈之后,我同意你只需要评估每个WHEN的一个任务,因为CASE语句一旦找到第一个TRUE语句就应该退出。但是,已将其更新为:CASE
WHEN UPPER(T.PRNAME) = 'EVALUATE TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1)
WHEN UPPER(T.PRNAME) = 'EVALUATE BRU MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1)
WHEN UPPER(T.PRNAME) = 'EVALUATE TSC MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1)
ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1)
END
我现在得到:
ORA-01427: single-row subquery returns more than one row
不确定为什么会出现这种情况,特别是在最后添加ROWNUM = 1
以确保只返回一个结果。
单独运行THEN时:
SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY')
FROM PRTASK T
WHERE T.PRPROJECTID = INV_INVESTMENTS.ID
AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE'
AND PRISMILESTONE = 1
AND ROWNUM = 1
我得到一个结果。如果我认为CASE语句一旦找到第一个TRUE语句就会退出,为什么会发现多行?
编辑2:好的 - 所以我一直在玩这个(因为我仍然无法找到合乎逻辑的答案,我已经取得了一些进展。我现在已经改变了查询结构的方式以下内容:
SELECT DISTINCT To_Char(T.PRFINISH, 'DD/MM/YY'),
T.PRNAME
FROM PRTASK T
LEFT OUTER JOIN INV_INVESTMENTS ON T.PRPROJECTID = INV_INVESTMENTS.ID
WHERE T.PRNAME = CASE
WHEN (T.PRNAME = 'Concept Tech PEP Meeting Date' AND T.PRSTATUS != 2) THEN 'Concept Tech PEP Meeting Date'
WHEN (T.PRNAME = 'Concept BRU Meeting Date' AND T.PRSTATUS != 2) THEN 'Concept BRU Meeting Date'
WHEN (T.PRNAME = 'End of Concept Phase' AND T.PRSTATUS != 2) THEN 'End of Concept Phase'
WHEN (T.PRNAME = 'Evaluate Tech PEP Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate Tech PEP Meeting Date'
WHEN (T.PRNAME = 'Evaluate BRU Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate BRU Meeting Date'
WHEN (T.PRNAME = 'Evaluate TSC Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate TSC Meeting Date'
WHEN (T.PRNAME = 'End of Evaluate Phase' AND T.PRSTATUS != 2) THEN 'End of Evaluate Phase'
WHEN (T.PRNAME = 'End of Analyse Phase' AND T.PRSTATUS != 2) THEN 'End of Analyse Phase'
WHEN (T.PRNAME = 'End of Design Phase' AND T.PRSTATUS != 2) THEN 'End of Design Phase'
WHEN (T.PRNAME = 'End of Build Phase' AND T.PRSTATUS != 2) THEN 'End of Build Phase'
WHEN (T.PRNAME = 'End of Test Phase' AND T.PRSTATUS != 2) THEN 'End of Test Phase'
WHEN (T.PRNAME = 'In Service' AND T.PRSTATUS != 2) THEN 'In Service'
WHEN (T.PRNAME = 'End of Implement Phase' AND T.PRSTATUS != 2) THEN 'End of Implement Phase'
WHEN (T.PRNAME = 'End of Closure Phase' AND T.PRSTATUS != 2) THEN 'End of Closure Phase'
ELSE 'In Service'
END
AND INV_INVESTMENTS.CODE = '007058'
但是,现在,我正在获取多个返回值的WHEN语句。任何人都可以确认CASE语句是否真的只返回第一个TRUE值吗?
答案 0 :(得分:4)
T.PRNAME =' TECH PEP会议日期' AND T.PRNAME =' BRU会议日期'?我认为我们在这里有重叠的条件。
我在这里的高度假设是你有一张桌子,其中有许多任务,旁边有状态,那么我认为这里应该发生的事情如下所示。
首先是你的任务表,我自己创造了一些东西。
CREATE TABLE #testtask
(
PRID INT
, PRNAME varchar(50)
, PRSTATUS INT
, PREREQ INT
)
INSERT INTO #testtask VALUES
(1,'TECH PEP MEETING DATE',1,0),
(2,'BRU MEETING DATE',1,1),
(3,'TSC MEETING DATE',1,2)
必须是这样的
然后,我在自己的表上创建了一个与其先决任务相关的左连接。
SELECT
t1.PRNAME AS [Job]
, t1.PRSTATUS AS [JobStatus]
, t2.PRNAME AS [PreReqJob]
, t2.PRSTATUS AS [PreReqStatus]
INTO #taskList
FROM #testtask t1
LEFT JOIN #testtask t2
ON
t1.PREREQ = t2.PRID
以及以下结果。
在进入我认为是你的脚本检查每个任务状态与先决条件任务之前。
SELECT
CASE
WHEN tl.[Job] = 'TECH PEP MEETING DATE' AND tl.[JobStatus] != 2
THEN
-- do your max select here for 'Tech pep'
WHEN tl.[Job] = 'BRU MEETING DATE' AND tl.[JobStatus] != 2 AND tl.[PreReqStatus] = 2
THEN
-- do your max select here for 'Bru meet'
WHEN tl.[Job] = 'TSC MEETING DATE' AND tl.[JobStatus] != 2 AND tl.[PreReqStatus] = 2
THEN
-- do your max select here for 'Tsc meet'
ELSE
-- do your default max date
END AS [Date]
FROM #taskList AS tl
请单独了解这个概念,因为我没有你的实际表格。如果你复制整件事,你几乎会有错误。希望这有助于:)
答案 1 :(得分:2)
首先,针对lad2025指出的内容修复您的案例陈述,但不使用任何OR
,并简化为
CASE
WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN ...
WHEN T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2 THEN ...
WHEN T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2 THEN ...
ELSE ...
END
然后进一步简化使用案例来使用相同的查询
(
SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY')
FROM PRTASK T
WHERE T.PRPROJECTID = INV_INVESTMENTS.ID
AND PRISMILESTONE = 1
AND Upper(T.PRNAME) =
CASE
WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN 'TECH PEP MEETING DATE'
WHEN T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2 THEN 'BRU MEETING DATE'
WHEN T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2 THEN 'TSC MEETING DATE'
ELSE 'END OF EVALUATE PHASE'
END
)
答案 2 :(得分:2)
尝试回答ROWNUM = 1问题,你确定你在其中一个分支机构中运行吗?您没有在ELSE分支中指定ROWNUM = 1。在那里添加ROWNUM = 1会有帮助吗?
答案 3 :(得分:2)
嗯,
我试图找到你的问题,但是使用了很多未知的表。 为了获得更好的帮助,请尝试构建一些助手可以使用的sqlfiddle。
经过一些研究后,在我看来,如果你的查询只返回一行,那么oracle实际上并没有检查。它检查,如果你的语法似乎只允许一行。 我不确定这一点。
尝试在所有单个子查询返回字段周围使用max(x),如果oracle接受这个,请看一下。如果你真的只得到一行,那么max()不会改变你的值,所以要使用它。
答案 4 :(得分:1)
您的CASE WHEN
条件相互冲突,使用AND
时遇到问题。您的第2和第3 WHEN
将始终返回FALSE
,为什么?看看这一行..
WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2)
AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2)
THEN...
这一个T.PRNAME = 'TECH PEP MEETING DATE
与其旁边的AND
条件AND (T.PRNAME = 'BRU MEETING DATE'
发生冲突,该条件永远不会在您的第3个TRUE
如果AND
之间的两个条件为真,则使用AND
将仅返回true。
通过阅读您的代码,您的AND
代码中的WHEN
似乎需要由OR
替换,以更正/删除列T.PRNAME
中的冲突条件
以下代码是您的,我修改后将AND
替换为OR
来纠正您的情况。
CASE
WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2
THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1)
WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) OR (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2)
THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1)
WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) OR (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2)
THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1)
ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1)
END
希望这有帮助。