【发布时间】:2016-05-30 21:05:20
【问题描述】:
我在 Oracle 中处理日期最困难。由于日期问题,我发现自己花费数小时试图编译和运行查询。我不明白这有什么用。
我有一个文本字段 2015 年 4 月 23 日作为日期。我需要将此日期转换为两种形式; 2015 年 4 月和 2015 年 4 月 23 日。我已经想出了如何通过使用 TO_CHAR 和 TO_DATE 转换为这两种类型,但我的结果似乎不一致。
当我尝试转换为 MM/YYYY 格式时,出现此错误:ORA-01841: (full) year must be between -4713 and +9999, and not be 0
TO_DATE(hist.DATESTAMP, 'MM/YYYY')
如果我将其更改为TO_CHAR(hist.DATESTAMP, 'MM/YYYY'),它会按预期工作,但现在在给定日期之后显示项目的查询不再有效,因为它现在是字符串而不是日期。 WHERE DATESTAMP > '04/01/2015'
我有一个大的 csv 文件,我将数据导入到 Oracle 表中,需要提供关于它的报告。
我需要在日期上可以搜索结果,并且报告只显示月份和年份。通过 group by 组合了总计,以显示当月的总计。
在 SQL Server 中,我可以轻松完成这项任务。但是,Oracle 在处理日期时非常痛苦,我不知道如何使其正常工作。
我一直在阅读我能找到的所有日期来源,尤其是这里。在通过双重选择的真空中,我可以将字符串转换为日期,然后将该日期转换为我的月/年字符串。但是我的活动导入表在日期前后出现错误后继续抛出错误。
我可以使用一些真正的指导。谢谢
为好奇者准备的表格和脚本
CREATE TABLE MONTHLY_DATA
(
ID NUMBER(10) NOT NULL,
DATESTAMP DATE NOT NULL,
PARTNER VARCHAR2(256 BYTE) NOT NULL,
APPNAME VARCHAR2(256 BYTE) NOT NULL,
TYPE_NAME VARCHAR2(256 BYTE) NOT NULL,
PLATFORM VARCHAR2(10 BYTE) NOT NULL, -- RED or BLUE
VOLUME NUMBER(10) NOT NULL,
LBSSUMMARY VARCHAR2(5 BYTE) NOT NULL, -- TRUE or FALSE
CREATE_DTS DATE,
MODIFIED_DTS DATE,
LAST_MODIFIED_USER VARCHAR2(40 BYTE)
)
CREATE TABLE MONTHLY_SUMMARY
(
DATESTAMP DATE NOT NULL,
RED_VOLUME NUMBER(10) NOT NULL,
BLUE_VOLUME NUMBER(10) NOT NULL,
LBS_VOLUME NUMBER(10) NOT NULL,
CREATE_DTS DATE,
MODIFIED_DTS DATE,
LAST_MODIFIED_USER VARCHAR2(40 BYTE)
)
MONTHLY_DATA 中的数据每月大约有 50k 行。 目标是总结这些数据,并提供一个整体。
此外,NLS 设置为: select * from nls_session_parameters where parameter = 'NLS_DATE_FORMAT'; NLS_DATE_FORMAT: DD-MON-RR
按月分组的 MONTHLY_SUMMARY 的值。每个月应该只有 1 行;
03/2015 52 77 19
04/2015 34 76 21
这两个表都用于使用日期构建报告。使 where 子句变得简单;如上所述是什么 我在追WHERE DATESTAMP > '04/01/2015',但似乎我需要使用 TO_DATE 进行转换。
这是加载数据的脚本。
INSERT INTO MONTHLY_SUMMARY (DATESTAMP, RED_VOLUME, BLUE_VOLUME, LBS_VOLUME)
SELECT DISTINCT
MONTHLY_DATA.DATESTAMP,
CASE WHEN red.VOLUME IS NULL THEN 0 ELSE red.VOLUME END AS RED_VOLUME,
CASE WHEN blue.VOLUME IS NULL THEN 0 ELSE blue.VOLUME END AS BLUE_VOLUME,
CASE WHEN lbs.VOLUME IS NULL THEN 0 ELSE lbs.VOLUME END AS LBS_VOLUME
FROM MONTHLY_DATA hist
LEFT JOIN (SELECT DATESTAMP, SUM(hist.VOLUME) AS VOLUME
FROM MONTHLY_DATA md
WHERE PLATFORM = 'RED'
GROUP BY DATESTAMP) red
ON md.DATESTAMP = red.DATESTAMP
LEFT JOIN (SELECT DATESTAMP, SUM(hist.VOLUME) AS VOLUME
FROM MONTHLY_DATA md
WHERE PLATFORM = 'BLUE'
GROUP BY DATESTAMP) blue
ON md.DATESTAMP = blue.DATESTAMP
LEFT JOIN (SELECT DATESTAMP, SUM(MONTHLY_DATA.VOLUME) AS VOLUME
FROM MONTHLY_DATA
WHERE LBSSUMMARY = 'TRUE'
GROUP BY DATESTAMP) lbs
ON MONTHLY_DATA.DATESTAMP = lbs.DATESTAMP
WHERE MONTHLY_DATA.DATESTAMP
NOT IN (SELECT DISTINCT DATESTAMP FROM MONTHLY_SUMMARY)
GROUP BY
MONTHLY_DATA.DATESTAMP,
red.VOLUME,
blue.VOLUME,
lbs.VOLUME
ORDER BY 1;
【问题讨论】:
-
您是否从所有日期都有效的干净表格开始?您希望避免将导入的日期作为字符串存储到数据库表中的情况。如果其中一些字符串无效,则在您尝试在查询期间动态转换它们时它将失败。在进一步之前,最好完成将所有日期存储在表中 DATE 类型列中的数据清理练习。如果您已经做到了这一步,请告诉我们?
-
是的,该列已经过验证并且包含格式正确的日期。
-
我希望将日期保存为 DATE 数据类型。但是当我把它变成一个字符串时,转换似乎只部分起作用。
-
问题是您将日期存储为文本。你在这里讨论的每一个问题都源于此。此外,您的数据顺序也不好。 YYYY-MM-DD 或 YYYYMMDD 会更好,但仍不如日期。
-
更新为包含表格和脚本。