Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
Какой тип данных нужно использовать чтобы хранить в базе время, без информации о дате. Например, начало и конец лекции, с 8.30 и до 9.45. И чтобы над этими значениями можно было производить вычисления, например эта лекция идет 9.45-8.30=1 час 15 мин.
Я запутался в типах данных date, timestamp, interval, что когда применять и как извлекать из результата вычислений часы, минуты.
7 фев 07, 11:56    [3748916]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Sxak
Member

Откуда: Nsk
Сообщений: 516
number почему не годится?
7 фев 07, 11:58    [3748930]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Чего тыт сложного?
Guest
Вот, навскидку:

declare
d1 date:=to_date('09:45','hh24:mi');
d2 date:=to_date('08:30','hh24:mi');
begin
dbms_output.put_line( to_char(trunc((d1-d2)*24))||' часов '||
to_char((trunc((d1-d2)*24,2)-trunc((d1-d2)*24))*60)||' минут');
end ;

1 часов 15 минут
7 фев 07, 12:21    [3749134]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
mcwhite
Member

Откуда: Москва
Сообщений: 423
Для хранения дат предусмотрен, как минимум, тип DATE (не считая типов TIMESTAMP). Для манипулирования данными типа DATE в языках SQL и PL/SQL предлагается, не побоюсь этого слова, очень богатый выбор функций, операций...

В общем, см. SQL Reference, а также Concepts по Вашей версии Oracle.
7 фев 07, 12:34    [3749247]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Sxak
Member

Откуда: Nsk
Сообщений: 516
Чего тыт сложного?
Вот, навскидку:

declare
d1 date:=to_date('09:45','hh24:mi');
d2 date:=to_date('08:30','hh24:mi');
begin
dbms_output.put_line( to_char(trunc((d1-d2)*24))||' часов '||
to_char((trunc((d1-d2)*24,2)-trunc((d1-d2)*24))*60)||' минут');
end ;

1 часов 15 минут

Сложного то, что если ты сегодня запишешь в таблицу эти d2 d1 и завтра запишешь те же значения то они будут разные. Ибо реальной значение будет "сегодня в такое-то время" а завтра понятие сегодня будет уже другое. Кроме того усложнен (хоть и почти тривиален) проесс взятия даты зная время в таком виде и нужное число (придется делать
дата_число + (d1-trunc(d1)) - причем скобочек лишних нет
) А вот намбер очень подходит - это тип результата date-trunc(date) , правда несколько усложнен процесс вычисления нужного значения типа часов/24+минут/(24*60)+ ...
7 фев 07, 12:44    [3749317]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Elic
Member

Откуда:
Сообщений: 29976
В общем, см. SQL Reference, а также Concepts по Вашей версии Oracle.
А также STFF Selecting Datatype
7 фев 07, 12:45    [3749332]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
mcwhite
Для хранения дат предусмотрен, как минимум, тип DATE (не считая типов TIMESTAMP). Для манипулирования данными типа DATE в языках SQL и PL/SQL предлагается, не побоюсь этого слова, очень богатый выбор функций, операций...

Wasup!
Я запутался в типах данных date, timestamp, interval, что когда применять и как извлекать из результата вычислений часы, минуты.

Из документации понял, что timestamp это тот же date, но с возможностью хранить доли секунды и часовой пояс. Правильно?
А вот чем interval отличается от number (который и получается при date1-date2)?

Sxak
number почему не годится? ... date-trunc(date)

А если понадобится посчитать количество часов по всей таблице?
select sum(EndTime-StartTime) from mytable
Number подойдет?

Sxak
правда несколько усложнен процесс вычисления нужного значения типа часов/24+минут/(24*60)+ ...

А встроенные функции типа extract здесь применимы?
7 фев 07, 13:37    [3749820]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Sxak
Member

Откуда: Nsk
Сообщений: 516
Wasup!

Sxak
number почему не годится? ... date-trunc(date)

А если понадобится посчитать количество часов по всей таблице?
select sum(EndTime-StartTime) from mytable
Number подойдет?
Не очень понял. Что значит количество часов? Если есчть время начала start_time и время конца end_time и они хранятся в нумбер в том виде в кром я написал то select sum(end_time-start_time) прекрасно отработают и после умножения на 24 получишь количество часов (еще раз на 60 умножишь получишь минуты) По конкретной дате сов временем это значение намбер получаешь как date-trunc(date) Вот только да, ЕМНИП есть какой-то типа interval Вот только стучится ли он тут без понятия

Wasup!


Sxak
правда несколько усложнен процесс вычисления нужного значения типа часов/24+минут/(24*60)+ ...

А встроенные функции типа extract здесь применимы?

Не знаю. Я практически семерочник, в семерке такогоне было.. Может быть и пойдет. Проверь...
7 фев 07, 13:45    [3749877]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
Sxak Спасибо!

А кто-нибудь, кто работает со старшими версиями Оракла, подскажет о целесообразности применения interval, extract в моем случае?
7 фев 07, 13:50    [3749918]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Sxak
Если есчть время начала start_time и время конца end_time и они хранятся в нумбер в том виде в кром я написал то select sum(end_time-start_time) прекрасно отработают


Не все коты масле.

select
 dt,
 to_date(dt||' 04:00:00' , 'DD.MM.YYYY HH24:MI:SS')-
 to_date(dt||' 01:00:00' , 'DD.MM.YYYY HH24:MI:SS') tm
from
 (
  select to_char(to_date('01.01.2006', 'DD.MM.YYYY')+rownum, 'DD.MM.YYYY') dt
  from user_tab_columns
  where rownum < 366
 )
where to_char(to_date(dt, 'DD.MM.YYYY'), 'DAY', 'NLS_DATE_LANGUAGE=RUSSIAN') = 'ВОСКРЕСЕНЬЕ'
/


DT TM
---------- ----------
08.01.2006 ,125
15.01.2006 ,125
22.01.2006 ,125
29.01.2006 ,125
05.02.2006 ,125
12.02.2006 ,125
19.02.2006 ,125
26.02.2006 ,125
05.03.2006 ,125
12.03.2006 ,125
19.03.2006 ,125
26.03.2006 ,125
02.04.2006 ,125
09.04.2006 ,125
16.04.2006 ,125
23.04.2006 ,125
30.04.2006 ,125
07.05.2006 ,125
14.05.2006 ,125
21.05.2006 ,125
28.05.2006 ,125
04.06.2006 ,125
11.06.2006 ,125
18.06.2006 ,125
25.06.2006 ,125
02.07.2006 ,125
09.07.2006 ,125
16.07.2006 ,125
23.07.2006 ,125
30.07.2006 ,125
06.08.2006 ,125
13.08.2006 ,125
20.08.2006 ,125
27.08.2006 ,125
03.09.2006 ,125
10.09.2006 ,125
17.09.2006 ,125
24.09.2006 ,125
01.10.2006 ,125
08.10.2006 ,125
15.10.2006 ,125
22.10.2006 ,125
29.10.2006 ,125
05.11.2006 ,125
12.11.2006 ,125
19.11.2006 ,125
26.11.2006 ,125
03.12.2006 ,125
10.12.2006 ,125
17.12.2006 ,125
24.12.2006 ,125
31.12.2006 ,125

52 rows selected.

SQL>

Видно, что арифметика дат в Оракле не учитывает переход на летнее время и обратно.
7 фев 07, 14:38    [3750336]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Wasup!
Sxak Спасибо!

А кто-нибудь, кто работает со старшими версиями Оракла, подскажет о целесообразности применения interval, extract в моем случае?


ИМХО, нецелесообразно. Выражения с extract получаются очень громоздкими.
Для арифметики проще и эффективнее пользовать NUMBER. Продолжительность интервала, смещение от начала суток выражать целым числом секунд или минут (в зависимости от задачи, так для расписания занятий секунды не нужны).
Секунды или минуты преобразовать в interval раз плюнуть функцией numtodsinterval, зато назад заколебёшся. Преобразовать секунды в формат HH24:MI:SS и наоборот тоже достаточно просто.
7 фев 07, 14:56    [3750478]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
mcureenab
Для арифметики проще и эффективнее пользовать NUMBER. Продолжительность интервала, смещение от начала суток выражать целым числом секунд или минут (в зависимости от задачи, так для расписания занятий секунды не нужны).


Спасибо, mcureenab! На мой взгляд это лучший способ.
Просто проводить вычисления и преобразовывать в нужный формат. Например сколько прошло минут с учетом округлениея секунд.

select
	 to_char(to_date(time1,'SSSSS'),'hh24:mi') as Time
	,trunc(time1/3600) || ':' || round((time1-trunc(time1/3600)*3600)/60) as TimeRoundedToMinute  
from
(select to_number(to_char(to_date('09:04:59','hh:mi:ss'),'SSSSS')) time1 from dual)

TIME  TIMEROUNDEDTOMINUTE                                                       
----- --------------------------------------------------------------------------
09:04 9:5                                                                       
1 row selected

Кстати, а почему различается день? Что-то не так в настройках Оракла?

select
 to_char(sysdate,'dd.mm.yyyy') as a
,to_char(to_date('09:04:59','hh24:mi:ss'),'dd.mm.yyyy') as b
from dual
A          B         
---------- ----------
07.02.2007 01.02.2007
1 row selected
7 фев 07, 17:13    [3751711]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
Возник уже теоретический вопрос, а как посчитать общее время между событиями, если тип столбца timestamp, а не date?
Здесь начало события может быть в одном дне, а конец события в следующем. Нужно посчитать сколько длилось событие.
Для одной строки понятно - TimeStampEnd-TimeStampStart.
А для всей таблицы? Ведь timestamp-timestamp=interval, а Sum() не умеет работать с interval
8 фев 07, 14:07    [3756222]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Wasup!
Возник уже теоретический вопрос, а как посчитать общее время между событиями, если тип столбца timestamp, а не date?
Здесь начало события может быть в одном дне, а конец события в следующем. Нужно посчитать сколько длилось событие.
Для одной строки понятно - TimeStampEnd-TimeStampStart.
А для всей таблицы? Ведь timestamp-timestamp=interval, а Sum() не умеет работать с interval

тут
8 фев 07, 17:41    [3757880]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
Кстати, а почему различается день?

select
 to_char(sysdate,'dd.mm.yyyy') as a
,to_char(to_date('09:04:59','hh24:mi:ss'),'dd.mm.yyyy') as b
from dual
A          B         
---------- ----------
07.02.2007 01.02.2007
1 row selected

Что по умолчанию подставляется в дату в качестве дня, когда я задаю только время?
12 фев 07, 12:29    [3770833]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116064
Wasup!
Кстати, а почему различается день?

select
 to_char(sysdate,'dd.mm.yyyy') as a
,to_char(to_date('09:04:59','hh24:mi:ss'),'dd.mm.yyyy') as b
from dual
A          B         
---------- ----------
07.02.2007 01.02.2007
1 row selected

Что по умолчанию подставляется в дату в качестве дня, когда я задаю только время?


Неужели сами еще не догадались ?
12 фев 07, 12:32    [3770851]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
Первый день текущего месяца?!
Просто ожидал, что это будет текущий день.
13 фев 07, 11:55    [3776839]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
dmidek
Member

Откуда: Киев - Дортмунд
Сообщений: 116064
Wasup!
Первый день текущего месяца?!
Просто ожидал, что это будет текущий день.


Неверно ожидали.
Manipulating the Time Format
13 фев 07, 12:03    [3776916]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Elic
Member

Откуда:
Сообщений: 29976
Wasup!
Просто ожидал, что это будет текущий день.
STFF
13 фев 07, 12:07    [3776952]     Ответить | Цитировать Сообщить модератору
 Re: Как правильно хранить время в базе?  [new]
Wasup!
Member

Откуда:
Сообщений: 184
dmidek
Неверно ожидали.
Manipulating the Time Format


Ну да:

Time is stored in the following 24-hour format:

HH24:MI:SS

By default, the time in a DATE column is 12:00:00 A.M. (midnight) if no time portion is entered or if the DATE is truncated.

In a time-only entry, the date portion defaults to the first day of the current month.
14 фев 07, 10:33    [3782228]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить