powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / работа с датами до наше эры
12 сообщений из 12, страница 1 из 1
работа с датами до наше эры
    #39824697
ag_smith
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
добрый день, коллеги
помогите разобраться. Есть такой запрос, цель которого, вывести даты и соответствующие дни заданного интервала. Но, необходимо чтобы он работал с датами до нашей эры. Я пытаюсь внешним запросом убрать все даты нулевого года (которого быть не должно), но запрос ничего не выводит. Например, если ввести: 1) 28-12-0001 BC 2) 02-01-0001 AD
По идее должно выводиться 6 записей, с 28.12 по 02.01
Вот сам запрос

undefine start
undefine finish

select *
from(select to_char(to_date('&&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1, 'dd.mm.yyyy BC') my_date, to_char(to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1, 'Day') my_day
from (select 1, 2, 3 from dual group by cube(1,1,1,1,1,1,1,1,1,1))
where to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 2 < to_date('&&finish', 'dd-mm-yyyy BC', 'nls_date_language=english')) d
where
to_char(to_date(d.my_date, 'dd.mm.yyyy BC', 'nls_date_language=english')) <= to_date('31.12.0001 BC', 'dd.mm.yyyy BC', 'nls_date_language=english')
and to_char(to_date(d.my_date, 'dd.mm.yyyy BC', 'nls_date_language=english')) >= to_date('01.01.0001 AD', 'dd.mm.yyyy BC', 'nls_date_language=english');
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824724
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ag_smith,

если сравнивать теплое с мягким, то, скорее всего, ничего и не получится... Вы уж или все даты в строки приводите и сравнивайте между собой строки . Или наоборот - все строки переводите в дату и сравнивайте между собой даты.
А так намешали одно с другим, сдобрили всё это неявным преобразованием типов и удивляетесь полученному результату.
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824767
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С сотворением нашей эры не все так однозначно
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t1 as (select date '-1-12-31' d from dual)
select '+366+1' "до н.э.", d+366+1 d from t1
union all select '+1+366', d+1+366 from t1
union all select '+367', d+367 from t1;

до н.э D          
------ -----------
+366+1  0002-01-01
+1+366  0002-01-02
+367    0001-01-01
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824920
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-С сотворением нашей эры не все так однозначно
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
with t1 as (select date '-1-12-31' d from dual)
select '+366+1' "до н.э.", d+366+1 d from t1
union all select '+1+366', d+1+366 from t1
union all select '+367', d+367 from t1;

до н.э D          
------ -----------
+366+1  0002-01-01
+1+366  0002-01-02
+367    0001-01-01


В Oracle Database 19.2 та же картина:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
with t1 as (select TO_date('-0001.12.31', 'SYYYY.MM.DD') AS d from dual)
--
, T AS (
select ' ' AS add_days, d from t1
union all select '+0', d+0 from t1
union all select '-0', d-0 from t1
union all select '+1', d+1 from t1
union all select '+366', d+366 from t1
union all select '+367', d+367 from t1
union all select '+1+366', d+1+366 from t1
union all select '+366+1' , d+366+1 d from t1)
--
SELECT add_days, TO_CHAR(d, 'DD.MM.YYYY B.C.') AS dd_mm_yyyy_BC FROM t;

ADD_DA DD_MM_YYYY_BC  
------ ---------------
       31.12.0001 B.C.
+0     31.12.0001 B.C.
-0     31.12.0001 B.C.
+1     01.01.0001 A.D.
+366   31.12.0001 A.D.
+367   01.01.0001 A.D.
+1+366 02.01.0002 A.D.
+366+1 01.01.0002 A.D.

8 rows selected. 
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824960
ag_smith
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
на всякий случай, ниже привожу работающий вариант, если вдруг кто-то столкнется с такой же задачкой

undefine start
undefine finish

select *
from(select to_date('&&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1 my_date, to_char(to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1, 'Day') my_day
from (select 1, 2, 3 from dual group by cube(1,1,1,1,1,1,1,1,1,1))
where to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 2 < to_date('&&finish', 'dd-mm-yyyy BC', 'nls_date_language=english')) d
where
d.my_date <= to_date('31.12.0001 BC', 'dd.mm.yyyy BC', 'nls_date_language=english')
or d.my_date >= to_date('01.01.0001 AD', 'dd.mm.yyyy BC', 'nls_date_language=english');


коллеги, еще вопрос по этому коду. как организовать защиту от выхода за максимальный интервал oracle, то есть, если одна из дат (start / finish), или обе, введены больше 29.12.9999 AD, то чтобы они приравнивались 29.12.9999 AD? В sql я не силен)
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824981
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 -- Выполнено на Oracle Database 19.2

ADD_DA DD_MM_YYYY_BC  
------ ---------------
       31.12.0001 B.C.
+0     31.12.0001 B.C.
-0     31.12.0001 B.C.
+1     01.01.0001 A.D.
+366   31.12.0001 A.D.
+367   01.01.0001 A.D.
+1+366 02.01.0002 A.D.
+366+1 01.01.0002 A.D.

Неправильные результаты.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
WITH T AS (SELECT TO_DATE('31.12.-0001', 'DD.MM.SYYYY') as d FROM DUAL)
---
          SELECT TO_CHAR(d, 'DD.MM.SYYYY A.D.') AS res FROM t
UNION ALL SELECT TO_CHAR(d+(366), 'DD.MM.SYYYY A.D.') FROM t
UNION ALL SELECT TO_CHAR(d+(366+365), 'DD.MM.SYYYY A.D.') FROM t
UNION ALL SELECT TO_CHAR(d+(366+365+365), 'DD.MM.SYYYY A.D.') FROM t
UNION ALL SELECT TO_CHAR(d+(366+365+365+365), 'DD.MM.SYYYY A.D.') FROM t
UNION ALL SELECT TO_CHAR(d+(366+365+365+365+366), 'DD.MM.SYYYY A.D.') FROM t;

RES
----------------
31.12.-0001 B.C.
31.12. 0001 A.D.
31.12. 0001 A.D.
31.12. 0002 A.D.
31.12. 0003 A.D.
31.12. 0004 A.D.


Здесь регулярно теряется один год.

Нужно заводить Service Request на сайте My Oracle Support (MOS)...

Проверьте, пожалуйста, что получается на менее свежих версиях базы.
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39824985
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ag_smithна всякий случай, ниже привожу работающий вариант, если вдруг кто-то столкнется с такой же задачкой
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
undefine start
undefine finish

select *
from(select to_date('&&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1 my_date
          , to_char(to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') + rownum - 1, 'Day') my_day
from (select 1, 2, 3 from dual group by cube(1,1,1,1,1,1,1,1,1,1))
where to_date('&start', 'dd-mm-yyyy BC', 'nls_date_language=english') 
              + rownum - 2 < to_date('&&finish', 'dd-mm-yyyy BC', 'nls_date_language=english')) d
where 
d.my_date <= to_date('31.12.0001 BC', 'dd.mm.yyyy BC', 'nls_date_language=english')
or d.my_date >= to_date('01.01.0001 AD', 'dd.mm.yyyy BC', 'nls_date_language=english');



коллеги, еще вопрос по этому коду. как организовать защиту от выхода за максимальный интервал oracle, то есть, если одна из дат (start / finish), или обе, введены больше 29.12.9999 AD, то чтобы они приравнивались 29.12.9999 AD? В sql я не силен)При оформлении кода используйте, пожалуйста, тэг SRC данного форума.
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39825000
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL*PlusНужно заводить Service Request на сайте My Oracle Support (MOS)...

Проверьте, пожалуйста, что получается на менее свежих версиях базы. Oracle Database 12c. Новые (/старые) грабли языка SQL
Нулевой год был високосным!
Bug с переходом через начало эры
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39825002
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL*PlusЗдесь регулярно теряется один год.

Нужно заводить Service Request на сайте My Oracle Support (MOS)...


И получишь иезуитский ответ date arithmetic используeт астрономическое нумерование годов .

SY.
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39825006
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL*PlusПроверьте, пожалуйста, что получается на менее свежих версиях базы.Отродясь так было и менять вряд решатся - могут быть системы, завязанные на юлианское число с лишними 366 днями с -4712.
Предполагаю алгоритм: в арифметике участвует нулевой високосный год. Если в результате операции получается нулевой год, берется следующий год. Если после этого получается несуществующий день 29 февраля плюс-первого года, берется 1 марта. Таким образом, 365 дней нулевого года дублируется на первый год, а первое марта троируется. Разный порядок суммирования с числами менее 60 и более дает разный результат. В обратном направлении нулевой год переводится в минус-первый, но проверка на 29 февраля не делается и поведение несколько иное:
Код: plsql
1.
2.
3.
4.
5.
select to_char(date '1-1-1' - 307, 'syyyy-mm-dd') zeroad from dual;

ZEROAD     
-----------
00000-00-00


При этом арифметика с другим несуществующим интервалом дат отрабатывает корректно.
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39825059
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
-2-При этом арифметика с другим несуществующим интервалом дат отрабатывает корректно.

Вы же про этот несуществующий интервал!?
https://ru.wikipedia.org/wiki/Григорианский_календарь Впервые григорианский календарь был введён папой римским Григорием XIII
в католических странах 4 октября 1582 года взамен прежнего юлианского:
следующим днём после четверга 4 октября стала пятница 15 октября.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SQL> WITH T AS (
  2  Select level as id, DATE '1582-10-01'+level-1 AS d
  3  FROM dual connect by level <= 7)
  4  --
  5  SELECT B.d AS b_d
  6       , A.d AS A_d
  7       , B.d - A.d AS days_between
  8  FROM T A, T B
  9  WHERE B.id = A.id + 1;

B_D         A_D         DAYS_BETWEEN
----------- ----------- ------------
02-OCT-1582 01-OCT-1582            1
03-OCT-1582 02-OCT-1582            1
04-OCT-1582 03-OCT-1582            1
15-OCT-1582 04-OCT-1582            1  
16-OCT-1582 15-OCT-1582            1
17-OCT-1582 16-OCT-1582            1


Ну так смогли же сделать!

Отчего бы не "допилить" тот интервал, который мы здесь обсуждаем?!
...
Рейтинг: 0 / 0
работа с датами до наше эры
    #39825092
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL*PlusОтчего бы не "допилить" тот интервал, который мы здесь обсуждаем?!

Ну мы то за, осталось самая малость - убедить Oracle . Правда последние так лет 25 они упорно твердят - not a bug.

SQL*PlusНу так смогли же сделать!

Cделали да не доделали. Вводился Грегорианский каледарь в разных странах в разное время. Посему наример в java есть setGregorianChange. А в Oracle только 15 Октября 1582. Так-что работая например с российскими датaми (15 Января 1918) и с ангийскими (14 Сентября 1752) и кучей других стран обломс.

SY.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / работа с датами до наше эры
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]