【问题标题】:Oracle SQL Previous Month query issueOracle SQL 上个月查询问题
【发布时间】:2010-11-26 16:45:31
【问题描述】:

到目前为止,我得到了以下内容:

SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month",
       TO_CHAR(sysdate, 'mm')-1 as "Current_Month"
  FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES"
 WHERE "Depart_Month" = "Current_Month"

但是这给了我一个错误:

ORA-00904:“Current_Month”:标识符无效

但是,如果没有 WHERE 子句,它可以正常工作。有什么想法吗?

【问题讨论】:

    标签: sql oracle ora-00904


    【解决方案1】:

    很遗憾,您无法在 WHERE 子句中引用列别名,因为它们尚不可用。你可以这样做:

    select  TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month",
              TO_CHAR(sysdate, 'mm')-1 as "Current_Month"
    from     "HOL_DEPART_DATES" "HOL_DEPART_DATES"
    where     TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') = TO_CHAR(sysdate, 'mm')-1
    

    或者这样做:

    select "Depart_Month", "Current_Month"
    from
    ( select  TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month",
              TO_CHAR(sysdate, 'mm')-1 as "Current_Month"
      from     "HOL_DEPART_DATES" "HOL_DEPART_DATES"
    )
    where     "Depart_Month" = "Current_Month"
    

    【讨论】:

    • 看准了,你们俩现在更有意义了!
    【解决方案2】:

    SELECT 子句在 SQL 中的 WHERE 子句之后计算。这就是为什么 WHERE 子句看不到您定义的别名的原因。

    要么:

    • 运行子查询:

      SELECT "Depart_Month", "Current_Month"
        FROM (SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM')
                        AS "Depart_Month",
                     TO_CHAR(SYSDATE, 'mm') - 1 AS "Current_Month"
                FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES")
       WHERE "Depart_Month" = "Current_Month"
      
    • 或使用 where 子句中的表达式:

      SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') AS "Depart_Month", 
             TO_CHAR(SYSDATE, 'mm') - 1 AS "Current_Month"
        FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES"
       WHERE TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') 
              = TO_CHAR(SYSDATE, 'mm') - 1
      

    【讨论】:

      【解决方案3】:

      我不会对来自 TO_CHAR 的返回值执行算术运算。 当从字符串 '01'(一月)中减去 1 时,我们不会得到 12(十二月)。

      你应该这样做:

      select *
        from hol_depart_dates
       where depart_date between trunc(add_months(sysdate, -1), 'MM')
                             and trunc(sysdate, 'MM') - interval '1' second;
      

      现在查询可以使用depart_date 上的索引。并且不必为每一行调用 TO_CHAR。

      【讨论】:

      • 因为您从 TRUNC(SYSDATE,'MM') 中减去一整天,您实际上错过了该月最后一天的任何出发日期(除非他们的时间正好是午夜 12 点)。
      • Opps,很好​​发现。现在已经修好了。
      【解决方案4】:

      如果您想比较日期,则不应将它们转换为字符串 - Oracle 内置了对日期/时间算法的支持。

      在您的情况下,您似乎正在查询出发日期的月份等于前一个月的表 - 这没有意义。如果当前是 11 月,则查询将返回 2010 年 10 月、2009 年 10 月、2008 年 10 月等的行。您确定这是您想要的吗?

      使用日期算术确定日期是否在上个月内的最佳方法之一是使用 TRUNC(date,'MONTH') 与 ADD_MONTHS( date,-1),获取一个月前的日期。

      SELECT  TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month",
              TO_CHAR(ADD_MONTHS(sysdate, -1), 'mm') as "Current_Month"
      FROM    "HOL_DEPART_DATES"
      WHERE   "HOL_DEPART_DATES"."DEPART_DATE"
              BETWEEN ADD_MONTHS(TRUNC(SYSDATE,'MONTH'),-1)
              AND     TRUNC(SYSDATE,'MONTH') - 0.00001;
      

      “0.00001”从日期中减去一秒,因此日期范围实际上变为(假设现在是 2010 年 11 月)2010 年 10 月 1 日 00:00:00 到 2010 年 10 月 31 日 23:59:59。

      另一种等效的语法是:

      SELECT  TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month",
              TO_CHAR(ADD_MONTHS(sysdate, -1), 'mm') as "Current_Month"
      FROM    "HOL_DEPART_DATES"
      WHERE   "HOL_DEPART_DATES"."DEPART_DATE"
              >= ADD_MONTHS(TRUNC(SYSDATE,'MONTH'),-1)
      AND     "HOL_DEPART_DATES"."DEPART_DATE" < TRUNC(SYSDATE,'MONTH');
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-28
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 2016-02-20
        • 1970-01-01
        相关资源
        最近更新 更多