【问题标题】:WHERE CASE returning multiple rowsWHERE CASE 返回多行
【发布时间】:2015-10-16 00:58:12
【问题描述】:

我希望这个查询只返回一行。我将 CASE 语句的 WHEN 子句按照它们最有可能出现的顺序放置在那里,因此最有可能的 TRUE 语句将始终首先被评估。然而,似乎每个 WHEN 语句都在查询完成之前被评估,尽管它找到了多个 TRUE 语句。

SELECT To_Char(T.PRFINISH, 'DD/MM/YY') FINISH,
       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 子句为真。我认为当他们找到一个 TRUE 语句时,CASE 语句就完成了。

编辑:也许我解释得不好,让我们试试这个:

INV_INVESTMENTS 表中的每个 ID 都是一个项目。每个项目在 PRTASK 表中都有一组任务。在这个 PRTASK 表中,我们将拥有任务名称 (PRNAME)、状态 (PRSTATUS) 和完成日期 (PRFINISH)。任务列表按它们在项目中出现的顺序是:

1.概念技术 PEP 会议日期
2。概念 BRU 会议日期
3。概念阶段结束
4.评估技术 PEP 会议日期
5.评估 BRU 会议日期
6.评估 TSC 会议日期

其余任务按照我在 CASE 语句中列出的顺序排列。我希望此查询返回的是列表中第一个任务的完成日期,其 PRSTATUS 为 0 或 1。

【问题讨论】:

  • CASE 会针对表中的每一行进行评估。与WHERE 条件匹配的所有行都包含在结果集中。我认为您错误地使用了CASE 语句。对于带有PRSTATUS != 2 [and PNAME among those included, which appears to be all of them] OR PRNAME = 'In Service' AND INV_INVESTMENTS.CODE = '007058' 的每一行,WHERE 子句将评估为 TRUE,并返回该行。也许如果您提供示例输入数据和预期结果,我可以尝试编写查询。
  • @Turophile,我正在尝试仅返回其中一个 T.PRNAME 的完成日期。虽然多个可能是真的,但一次只有一个是相关的(并且按列出的顺序相关,即一旦概念技术 PEP 会议日期的 PRSTATUS 为 2,即在数据库中表示已完成,概念 BRU 会议日期就成为我想要找到的内容)。我一直在试图找出逻辑上写这个的最佳方法。我的逻辑是,如果它们按出现顺序排列,那么我总是会找到下一个最相关的 PRNAME。我想情况并非如此。
  • PRSTATUS 是干什么用的?
  • @AlexBuyny,PRSTATUS 的值为 0(未开始)、1(已开始)或 2(已完成)。我希望使用它来移动到列表中下一个相关的 PRNAME,因为前面的每个 PRNAME 的 PRSTATUS 都应该是 2,然后它就不再相关了。
  • @MatthewPaxman 然后看起来您只对 PRSTATUS = 2 的人感兴趣,我将其包含在下面的查询中

标签: sql case


【解决方案1】:

试试这个。您可以将已知名称放入表中,然后在连接中使用它。这会将您的选择简化为以下内容:

SELECT TOP 1 To_Char(T.PRFINISH, 'DD/MM/YY') FINISH,
       T.PRNAME  
FROM  PRTASK T
      LEFT OUTER JOIN INV_INVESTMENTS ON T.PRPROJECTID = INV_INVESTMENTS.ID
      JOIN ( 
      SELECT 'Concept Tech PEP Meeting Date' as Name, 1 as [Order]
      UNION All
      SELECT '<your next PRNAME here', 2 as [Order]
      UNION ALL ...
      ) names on names.Name = T.PRNAME
where PRSTATUS IN (0,1) AND PRINV_INVESTMENTS.CODE = '007058'
ORDER BY names.Order

【讨论】:

  • 抱歉,我应该提一下,我只有对我要从中查询此信息的数据库的读取权限,所以我无法创建表。
  • 你可以像上面那样把你熟知的 prnames 放到一个内部 select 语句中
  • 花了我一秒钟才意识到我需要从 DUAL (Oracle) 中进行选择,但除此之外这非常有效。谢谢大佬,这个我也没想到。我被 CASE 困住了,没有考虑其他选择。
【解决方案2】:

我仍然不明白您要做什么(没有给出示例数据/结果),但我会像这样重组它:

SELECT To_Char(PRFINISH, 'DD/MM/YY') AS FINISH, PRNAME
FROM ( 
  SELECT MAX(PRFINISH),
         PRNAME  
  FROM  PRTASK AS T
  WHERE  (PRNAME = 'In Service' OR PRSTATUS != 2)
  AND    PRPROJECTID IN 
    (SELECT ID 
     FROM INV_INVESTMENTS
     WHERE CODE = '007058' )
  GROUP BY PRNAME
  ) AS TABLE1

注意,这是假设您在查询中列出了 PRNAME 的所有可能值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多