Преобразование серии дат в календаре было ошибкой в ​​моем запросе - PullRequest
0 голосов
/ 15 мая 2019

Я выполняю этот запрос, чтобы преобразовать мой календарь из 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;

Хэнк для вашего руководства

1 Ответ

1 голос
/ 15 мая 2019

Не знаком с: 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 не имеет формата. Он представляет момент времени без какой-либо конкретной записи. Формат становится актуальным только при преобразовании даты в строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...