【问题标题】:Start a Case Statement without an outside 'Select' - CTE's开始一个没有外部“选择”的案例陈述 - CTE
【发布时间】:2015-07-02 18:35:40
【问题描述】:

运行此查询(如下)返回“值过多”错误:

select 
case
     when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm') || '01'
     then (select FirstReportGroups.*, FirstReportDetails.*
           from FirstReportGroups, FirstReportDetails)

     when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm') || '16'
     then (select SecondReportGroups.*, SecondReportDetails.*
           from SecondReportGroups, SecondReportDetails)
end as LetsSee
from cmtmpentered t1 join cmtmpconf t2    
      on t1.casenumber = t2.casenumber    
      and t1.enc = t2.enc 
;

我正在使用 CTE(它们不包括在内,因为它会使这很长),这对我来说合乎逻辑,但是谷歌搜索这个“太多值”错误并没有给我任何实质性帮助。单独运行 CTE 可以正常工作,所以这不是问题。

我认为,如果我只能摆脱外部的“选择”语句并将选择保留在案例中,那么一切都会解决。如果我解释得不好,我正在寻找的一个例子是:

case
     when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm') || '01'
     then (select FirstReportGroups.*, FirstReportDetails.*
           from FirstReportGroups, FirstReportDetails)

     when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm') || '16'
     then (select SecondReportGroups.*, SecondReportDetails.*
           from SecondReportGroups, SecondReportDetails)
end as LetsSee
;

这在任何情况下都可行吗?这种语法显然不起作用,否则我不会问这个问题 - 但有没有相关的方法可以做到这一点?

【问题讨论】:

  • caseselect 语句中只返回一个值。您可以在 PL/SQL 代码中使用if
  • 您到底想要输出什么?似乎是 UNION 或 WITH 的情况,具体取决于您实际想要看到的内容。

标签: sql oracle oracle11g common-table-expression


【解决方案1】:
select FirstReportGroups.*, FirstReportDetails.*
from       (select 1 a from dual) FirstReportGroups
cross join (select 2 b from dual) FirstReportDetails
where extract(day from sysdate) = 1
---------
union all
---------
select SecondReportGroups.*, SecondReportDetails.*
from       (select 3 a from dual) SecondReportGroups
cross join (select 4 b from dual) SecondReportDetails
where extract(day from sysdate) = 16;
  1. 将公用表表达式替换为内联视图。 CTE 仅在被多次引用时才应使用。对于只习惯于程序代码的程序员来说,它们可能看起来更好一些小例子。严重的 SQL 需要多个嵌套级别的内联视图。如果没有 CTE,调试会容易得多 - CTE 使突出显示和运行代码子块变得困难。
  2. 用谓词替换 case 表达式以按日期过滤。 CASE 表达式只能返回单个值。您可能可以对类型做一些花哨的事情,但这会非常复杂。我的代码仍然假设这两个集合返回相同类型的值。如果不是这样,您需要在应用程序级别做一些不同的事情。
  3. to_char 替换为extract Oracle 中的日期处理可能会令人困惑。诀窍是将所有内容保持在其本机类型中。除了格式化显示之外,您几乎不需要使用to_charto_date。对于任何其他操作,几乎可以肯定有一个函数可以在不转换类型的情况下处理它。
  4. , 替换为ANSI 语法cross join ANSI 样式语法有几个优点。一个主要优点是它可以清楚地表明何时有意进行交叉连接。

【讨论】:

  • 嗯,这至少是在编译和运行,所以很好。我无法理解 (select 1 a from dual) 等实际上在做什么。如果我删除它们,则不会选择任何行。你能扩展那部分吗?为什么我不能只说来自 FirstReportGroups?
  • select 1 a from dual 只是一个占位符,表示您用于这些 CTE 的完整查询。它也可以简单地使用from FIrstReportGroups,但在很多情况下,用常规内联视图(也称为子查询)替换 CTE 会很有帮助。
  • 是的,我知道它们是占位符,只是不知道如何理解它的语法。我现在明白了!我也有它的工作!非常感谢。
【解决方案2】:

您没有为LetsSee 指定连接条件。您实际上是在将LetsSeefrom 子句的结果交叉加入:

from cmtmpentered t1 
    join cmtmpconf t2 on t1.casenumber = t2.casenumber and t1.enc = t2.enc

我建议你加入LetsSeet1t2

另外,您没有为对指定连接条件:

  • FirstReportGroupsFirstReportDetails
  • SecondReportGroupsSecondReportDetails

【讨论】:

    猜你喜欢
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    相关资源
    最近更新 更多