10

我有一个包含以下字段的表:

报告(表名) Rep_Date(日期) Rep_Time(日期)

Rep_Time 字段的值类似于“01/01/1753 07:30:00”,即时间部分是相关的。我写了以下查询:

select Reports.pid, MaxDate from Reports
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY')
        || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate
    from reports
    group by pid
) ReportMaxDate
on Reports.PID = ReportMaxDate.PID
AND To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE
WHERE REPORTS.PID=61

查询的派生表部分运行,但是当我运行整个查询时出现错误:“不是有效月份”。为什么是这样?

为了帮助调试这个;如果我运行以下查询:

select rep_date, rep_time from reports where pid=61 and rownum=1

我得到:

Rep_Date = 01/04/2009
Rep_Time = 01/01/1753 13:00:00

更新 15:58 我现在可以执行以下查询:

select Reports.pid, MaxDate from Reports
INNER JOIN (
    select pid, max(TO_DATE(TO_CHAR(REP_DATE, 'DD/MM/YYYY')
        || TO_CHAR(REP_TIME, 'HH24:MI:SS'), 'DD/MM/YYYY HH24:MI:SS')) As MaxDate
    from reports group by pid
) ReportMaxDate
on Reports.PID = ReportMaxDate.PID
AND to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE
WHERE REPORTS.PID=61

但是,我需要在将WHEREMaxDate 的时间部分与 rep_time 进行比较的子句中再添加一条语句:to_date(to_char(maxdate,'MM/DD/YYYY'),'MM/DD/YYYY') = REP_DATE不起作用。

4

3 回答 3

28

1.

To_Date(To_Char(MaxDate, 'DD/MM/YYYY')) = REP_DATE

导致问题。当您使用不带时间格式的 to_date 时,oracle 将使用当前会话 NLS 格式进行转换,在您的情况下可能不是“DD/MM/YYYY”。检查这个...

SQL> select sysdate from dual;

SYSDATE
---------
26-SEP-12

Which means my session's setting is DD-Mon-YY

SQL> select to_char(sysdate,'MM/DD/YYYY') from dual;

TO_CHAR(SY
----------
09/26/2012


SQL> select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual;
select to_date(to_char(sysdate,'MM/DD/YYYY')) from dual
               *
ERROR at line 1:
ORA-01843: not a valid month

SQL> select to_date(to_char(sysdate,'MM/DD/YYYY'),'MM/DD/YYYY') from dual;

TO_DATE(T
---------
26-SEP-12

2.

更重要的是,为什么要转换为 char 再转换为 date,而不是直接比较

MaxDate = REP_DATE

如果您想在比较之前忽略 MaxDate 中的时间分量,您应该使用..

trunc(MaxDate ) = rep_date

反而。

==更新:基于更新的问题。

Rep_Date = 01/04/2009 Rep_Time = 01/01/1753 13:00:00

我认为问题更复杂。如果 rep_time 只是时间,那么您不能将其作为日期存储在数据库中。它必须是一个字符串或日期到时间间隔或数字为秒(感谢亚历克斯,看到这个)。如果可能的话,我建议使用一个同时包含日期和时间的列 rep_date 并将其直接与最大日期列进行比较。

如果它是一个正在运行的系统并且你无法控制更新,你可以试试这个。

trunc(rep_date) = trunc(maxdate) and 
to_char(rep_date,'HH24:MI:SS') = to_char(maxdate,'HH24:MI:SS')

无论哪种方式,时间都存储不正确(从 1753 年就可以看出),并且可能存在其他问题。

于 2012-09-26T14:32:04.220 回答
3

要知道实际的日期格式,请使用 sysdate 插入一条记录。这样您就可以找到实际的日期格式。例如

insert into emp values(7936, 'Mac', 'clerk', 7782, sysdate, 1300, 300, 10);

现在,选择插入的记录。

select ename, hiredate from emp where ename='Mac';

结果是

ENAME   HIREDATE
Mac     06-JAN-13

瞧,现在找到了您的实际日期格式。

于 2013-01-06T21:52:49.517 回答
1

您还可以使用 ALTER SESSION 命令为您的会话更改此数据库参数的值,并根据需要使用它

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY';
SELECT TO_DATE('05-12-2015') FROM dual;

05/12/2015
于 2020-11-23T05:09:42.870 回答