【问题标题】:Invalid Identifier error message on left outer join using subqueries使用子查询的左外连接出现无效标识符错误消息
【发布时间】:2015-06-30 17:42:55
【问题描述】:

仅当我用“*”替换顶部选择列时,此查询才有效。我一直在阅读与我类似的其他问题,但我无法将它们的逻辑应用于我的情况。所有子查询都是相同的,只是它们根据“where”子句中的状态而变化。

每天都有更多的成功。故障和警告不会每天都发生,所以它们有一些我想设为 0 的空值。我希望所有成功、警告和失败都与 a.Start_date 相关。

        Select a.START_DATE, a.Successes, b.START_DATE, b.Failures, c.START_DATE, c.WARNINGS

        FROM

        (
                Select 

                        (Case :P1_DATE_CHOOSER 
                             WHEN 'Daily' THEN trunc(start_time)
                             WHEN 'Weekly' THEN trunc(start_time, 'WW')
                             WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                        END) "START_DATE",
                    NVL(count(job_id),0) as "Successes"
            from NI_INFA_ACTIVITY_LOG_V
            where State = 1

            and
            (:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
            OR

            :P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND 
                            (1440*(END_TIME - START_TIME)) <= 5
            OR

            :P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND 
                            (1440*(END_TIME - START_TIME)) <= 20
            OR
            :P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
            OR
            :P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)

            group by Case :P1_DATE_CHOOSER 
                             WHEN 'Daily' THEN trunc(start_time)
                             WHEN 'Weekly' THEN trunc(start_time, 'WW')
                             WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                        END
            order by Case :P1_DATE_CHOOSER 
                             WHEN 'Daily' THEN trunc(start_time)
                             WHEN 'Weekly' THEN trunc(start_time, 'WW')
                             WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                        END

        ) a
        left outer join

        (
                   Select 

                            (Case :P1_DATE_CHOOSER 
                                 WHEN 'Daily' THEN trunc(start_time)
                                 WHEN 'Weekly' THEN trunc(start_time, 'WW')
                                 WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                            END) "START_DATE",
                        nvl(count(job_id),0) as "Failures"
                from NI_INFA_ACTIVITY_LOG_V
                where State = 3

                and
                (:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
                OR

                :P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND 
                                (1440*(END_TIME - START_TIME)) <= 5
                OR

                :P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND 
                                (1440*(END_TIME - START_TIME)) <= 20
                OR
                :P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
                OR
                :P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
                group by Case :P1_DATE_CHOOSER 
                                 WHEN 'Daily' THEN trunc(start_time)
                                 WHEN 'Weekly' THEN trunc(start_time, 'WW')
                                 WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                            END
                order by Case :P1_DATE_CHOOSER 
                                 WHEN 'Daily' THEN trunc(start_time)
                                 WHEN 'Weekly' THEN trunc(start_time, 'WW')
                                 WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                            END

        ) b
        on
        a.START_DATE = b.START_DATE

        left outer join

        (
        Select 

                    (Case :P1_DATE_CHOOSER 
                         WHEN 'Daily' THEN trunc(start_time)
                         WHEN 'Weekly' THEN trunc(start_time, 'WW')
                         WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                    END) "START_DATE",
                nvl(count(job_id),0) as "Warnings"
        from NI_INFA_ACTIVITY_LOG_V
        where State = 2



        and
        (:P1_JOB_SIZE_CHOOSER = 'Tiny' AND (1440*(END_TIME - START_TIME)) <= 1
        OR

        :P1_JOB_SIZE_CHOOSER = 'Small' AND (1440*(END_TIME - START_TIME)) > 1 AND 
                        (1440*(END_TIME - START_TIME)) <= 5
        OR

        :P1_JOB_SIZE_CHOOSER = 'Medium' AND (1440*(END_TIME - START_TIME)) > 5 AND 
                        (1440*(END_TIME - START_TIME)) <= 20
        OR
        :P1_JOB_SIZE_CHOOSER = 'Large' AND ((1440*(END_TIME - START_TIME)) > 20)
        OR
        :P1_JOB_SIZE_CHOOSER NOT IN('Small','Medium','Large','Tiny') AND (1440*(END_TIME - START_TIME)) > 0)
        group by Case :P1_DATE_CHOOSER 
                         WHEN 'Daily' THEN trunc(start_time)
                         WHEN 'Weekly' THEN trunc(start_time, 'WW')
                         WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                    END
        order by Case :P1_DATE_CHOOSER 
                         WHEN 'Daily' THEN trunc(start_time)
                         WHEN 'Weekly' THEN trunc(start_time, 'WW')
                         WHEN 'Monthly' THEN trunc(start_time, 'MM') 
                    END

        ) c

        on
        a.START_DATE = c.START_DATE
        ORDER BY
        a.START_DATE

最后,我希望结果类似于:

Start_Date  Successes  Warnings  Failures
6/1/2015            5         0         3
........            8        15         4
6/30/2015           9         1         0

【问题讨论】:

  • 你有没有过失败或警告但没有成功的一天?如果可能发生,则不会报告这些情况。
  • 即使设置了最苛刻的参数,一天通常也有超过 1000 次成功!感谢您指出这一点,但我相信这几乎是不可能的

标签: sql oracle subquery left-join


【解决方案1】:

您已经为子查询中的(某些)别名使用了带引号的标识符,因此您也必须在外部选择中引用这些标识符,并且与您使用的大小写完全匹配:

Select a.START_DATE, a."Successes",
  b.START_DATE, b."Failures",
  c.START_DATE, c."Warnings"
...

带引号的标识符很痛苦。如果您希望列标题大小写混合,您可以在子查询中使用不带引号的标识符,并在外部查询中应用最终的带引号的名称作为另一个别名;或让客户处理该显示问题。

由于start_date 是连接条件,您可能不希望所有三个引用;并且要在结果集中获得零,您需要对失败和警告计数进行 NVL,因此您最好还是使用不带引号的标识符:

Select a.start_date "Start date", a."Successes",
  nvl(b.failures, 0) "Failures", nvl(c.warnings, 0) "Warnings"
...
                    NVL(count(job_id),0) as successes
...

您已经拥有的围绕计数的 NVL 没有做任何事情 - 它需要在外部查询中而不是如图所示 - 因为如果计数为空,则没有开始日期值可分组。


如果子查询真的非常相似,您可以将其简化为具有三个选择性计数的单个查询级别;类似:

Select to_char(Case :P1_DATE_CHOOSER 
    WHEN 'Daily' THEN trunc(start_time)
    WHEN 'Weekly' THEN trunc(start_time, 'WW')
    WHEN 'Monthly' THEN trunc(start_time, 'MM') 
  END, 'MM/DD/YYYY') as "Start date",
  count(case when State = 1 then job_id end) as "Successes",
  count(case when State = 3 then job_id end) as "Failures",
  count(case when State = 2 then job_id end) as "Warnings"
from NI_INFA_ACTIVITY_LOG_V
where (:P1_JOB_SIZE_CHOOSER = 'Tiny'
    AND (1440*(END_TIME - START_TIME)) <= 1)
  OR (:P1_JOB_SIZE_CHOOSER = 'Small'
    AND (1440*(END_TIME - START_TIME)) > 1
    AND (1440*(END_TIME - START_TIME)) <= 5)
  OR (:P1_JOB_SIZE_CHOOSER = 'Medium'
    AND (1440*(END_TIME - START_TIME)) > 5
    AND (1440*(END_TIME - START_TIME)) <= 20)
  OR (:P1_JOB_SIZE_CHOOSER = 'Large'
    AND (1440*(END_TIME - START_TIME)) > 20)
  OR (:P1_JOB_SIZE_CHOOSER NOT IN ('Small','Medium','Large','Tiny') 
    AND (1440*(END_TIME - START_TIME)) > 0)
group by Case :P1_DATE_CHOOSER 
    WHEN 'Daily' THEN trunc(start_time)
    WHEN 'Weekly' THEN trunc(start_time, 'WW')
    WHEN 'Monthly' THEN trunc(start_time, 'MM') 
  END
order by Case :P1_DATE_CHOOSER 
    WHEN 'Daily' THEN trunc(start_time)
    WHEN 'Weekly' THEN trunc(start_time, 'WW')
    WHEN 'Monthly' THEN trunc(start_time, 'MM') 
  END;

你的括号似乎也不正常,所以我试图纠正那些,但你可能故意做了一些我没有遵循的事情......

【讨论】:

  • @Philab - 我添加了一个没有子查询和连接的版本 - 我认为它是等价的。
【解决方案2】:

替换 Select a.START_DATE, a.Successes, b.START_DATE, b.Failures, c.START_DATE, ... 经过 Select a."START_DATE", a."Successes", b."START_DATE", b."Failures", c."START_DATE", ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多