我运行此查询将日历从GREGORIAN转换为PERSIAN日期模式。 可以,但是在波斯模式下的某一天,该月有31天,因此无法将其转换为波斯模式,原因是“ ORA-01839”。
发生这种情况是因为我知道波斯模型的日期是完全正确的。
在此示例中,波斯日历的第二个月为31天。但是当我在(19,20,21)之间更改日期时,Oracle会显示“ ORA-01839”错误
-成功执行
SELECT TO_DATE(TO_CHAR(CAST(SUBSTR('18-MAY-18', 1, 10) AS DATE),
'YYYYMMDD',
'NLS_CALENDAR=PERSIAN'),
'YYYYMMDD') date_inventory
FROM DUAL W;
-引发错误ORA-01839
SELECT TO_DATE(TO_CHAR(CAST(SUBSTR('19-MAY-18', 1, 10) AS DATE),
'YYYYMMDD',
'NLS_CALENDAR=PERSIAN'),
'YYYYMMDD') date_inventory
FROM DUAL W;
在下个月,我遇到了以上错误。请注意,这个问题仅在2018年和其他年份有所不同。
MAY (19,20,21)
JUL (22)
AUG(21)
SEP(22)
我使用下面的查询来计算库存过程,但无法更改
create table TREND_WAREHOUSE
(
id NUMBER(30) not null,
reg_date NUMBER(30),
org_id NUMBER(30),
goods_id NUMBER(30),
qty NUMBER(30),
reg_datetime TIMESTAMP(6)
)
insert into TREND_WAREHOUSE (id, reg_date, org_id, goods_id, qty, reg_datetime)
values (1, 13970631, 10, 1, 100, to_timestamp('22-09-2018 00:00:00.000000', 'dd-mm-yyyy hh24:mi:ss.ff'));
insert into TREND_WAREHOUSE (id, reg_date, org_id, goods_id, qty, reg_datetime)
values (2, 13930609, 10, 1, 20, to_timestamp('31-08-2014 14:03:44.689000', 'dd-mm-yyyy hh24:mi:ss.ff'));
insert into TREND_WAREHOUSE (id, reg_date, org_id, goods_id, qty, reg_datetime)
values (3, 13940902, 10, 1, -20, to_timestamp('23-11-2015 00:00:00.000000', 'dd-mm-yyyy hh24:mi:ss.ff'));
insert into TREND_WAREHOUSE (id, reg_date, org_id, goods_id, qty, reg_datetime)
values (4, 13940902, 10, 1, 100, to_timestamp('23-11-2015 00:00:00.000000', 'dd-mm-yyyy hh24:mi:ss.ff'));
insert into TREND_WAREHOUSE (id, reg_date, org_id, goods_id, qty, reg_datetime)
values (5, 13940902, 10, 1, 300, to_timestamp('23-11-2015 00:00:00.000000', 'dd-mm-yyyy hh24:mi:ss.ff'));
commit;
WITH date_inventory_range AS
(SELECT TRUNC(MIN(date_inventory), 'MONTH') AS first_date_inventory,
ADD_MONTHS(TRUNC(MAX(date_inventory), 'MONTH'), 1) - 1 AS last_date_inventory
FROM (SELECT W.ORG_ID,
W.GOODS_ID,
TO_DATE(TO_CHAR(CAST(SUBSTR(W.REG_DATETIME, 1, 10) AS DATE),
'YYYYMMDD',
'NLS_CALENDAR=PERSIAN'),
'YYYYMMDD') date_inventory,
SUM(W.QTY) amount
FROM TREND_WAREHOUSE W
GROUP BY W.ORG_ID,
W.GOODS_ID,
CAST(SUBSTR(W.REG_DATETIME, 1, 10) AS DATE)
ORDER BY 3)),
all_dates AS
(SELECT first_date_inventory + LEVEL - 1 AS date_inventory
FROM date_inventory_range
CONNECT BY LEVEL <= 1 + last_date_inventory - first_date_inventory),
dense_data AS
(SELECT s.org_id,
s.goods_id,
TRUNC(d.date_inventory, 'MONTH') AS mnth,
NVL(SUM(s.amount) OVER(PARTITION BY s.org_id,
s.goods_id ORDER BY d.date_inventory),
0) AS total_amount
FROM all_dates d
LEFT OUTER JOIN (SELECT W.ORG_ID,
W.GOODS_ID,
TO_DATE(TO_CHAR(CAST(SUBSTR(W.REG_DATETIME, 1, 10) AS DATE),
'YYYYMMDD',
'NLS_CALENDAR=PERSIAN'),
'YYYYMMDD') date_inventory,
SUM(W.QTY) amount
FROM TREND_WAREHOUSE W
WHERE W.Org_Id = 10
and W.Goods_Id = 1
GROUP BY W.ORG_ID,
W.GOODS_ID,
CAST(SUBSTR(W.REG_DATETIME, 1, 10) AS DATE)
ORDER BY 3) s PARTITION BY(s.org_id, s.goods_id)
ON s.date_inventory = d.date_inventory)
SELECT org_id,
goods_id,
TO_CHAR(mnth, 'YYYY-MM') AS month,
AVG(total_amount) AS month_avg
FROM dense_data
GROUP BY org_id, goods_id, mnth
ORDER BY org_id, goods_id, mnth;
感谢您的指导
答案 0 :(得分:1)
不熟悉:CAST(SUBSTR('19 -MAY-18',1,10)AS DATE),因为我习惯于to_date函数并始终指定格式字符串。
这似乎正常工作:
select to_char(to_date('20190521', 'YYYYMMDD'), 'YYYYMMDD', 'NLS_CALENDAR=PERSIAN')
from dual;
哪里出错了,就是在不指定NLS_CALENDAR格式的情况下将此字符串转换回日期。所以你应该使用这个:
select to_date(to_char(to_date('20190521', 'YYYYMMDD'), 'YYYYMMDD', 'NLS_CALENDAR=PERSIAN')
,'YYYYMMDD'
,'NLS_CALENDAR=PERSIAN')
from dual;
最后的开始日期与您相同。
请注意,Oracle日期没有格式。它代表一个时间点,没有任何特定的符号。只有将日期转换为字符串时,格式才有意义。