Работа с полями TimeStamp в FB

Модераторы: kdv, CyberMax

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Работа с полями TimeStamp в FB

Сообщение Kotъ-Begemotъ » 11 авг 2007, 18:12

До этого работал с BDE (Paradox)
Есть у меня табличка заказов. Для простоты три поля - ID заказа, время начала выполнения и время окончания. Мне нужно выбрать все заказы время выполнения которых превышает 60 минут, и для каждого вывести время выполнения в минутах. Зная что минуте соответствует значение 0.000694444446708076 я и сделал запрос:

Код: Выделить всё

select od.OrderID, od.Start, od.Finish, (od.Finish - od.Start)/0.000694444446708076 TimRun
from Orders od
where od.Finish > od.Start and (od.Finish - od.Start)/0.000694444446708076 > 60 
order by 4 descending
И вуаля! Всё работало! Выбирались только заказы с временем выполнения больше 60 минут, и для каждого считалось время в минутах.

Сейчас пробую прогнать такой же запрос в IBExpert - ругается... Пишет "Arithmetic overflow or division by zero has occurred. arithmetic exception, numeric overflow, or string truncation."

В чём я неправ? И как вообще эту задачу реализовать?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 11 авг 2007, 20:50

прочитай вообще про хранение чисел в ib/fb. да и вообще, твое число и в парадоксе не влезает. и определись, где ты задаешь вопросы обычно, тут или на sql.ru.

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 11 авг 2007, 21:44

kdv писал(а):прочитай вообще про хранение чисел в ib/fb. да и вообще, твое число и в парадоксе не влезает. и определись, где ты задаешь вопросы обычно, тут или на sql.ru.
А где я ЭТОТ вопрос на sql.ru задавал?!? Один было дело - продублировал не зная что аудитория одна и та же, так извинился ведь! Подозреваю что дело в точности - слишком много цифирь видимо после десятичной точки... Про точность покурю обязательно, спасибо. Про умножение помню что точности суммируются, а про деление что-то упустил...

Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Re: Работа с полями TimeStamp в FB

Сообщение Slavik » 11 авг 2007, 22:25

Kotъ-Begemotъ писал(а):Зная что минуте соответствует значение 0.000694444446708076 я и сделал запрос
А не проще умножать на 1440 (24*60)?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 11 авг 2007, 22:43

А где я ЭТОТ вопрос на sql.ru задавал?!?
не задавал. но скачешь туда-сюда.

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 12 авг 2007, 00:58

kdv писал(а):
А где я ЭТОТ вопрос на sql.ru задавал?!?
не задавал. но скачешь туда-сюда.
А это плохо? Почему не использовать ДВА ресурса? Там тоже много интересного бывает. Или это здесь "моветон", а sql.ru - "запретная зона" которую посещать "некомильфо"? ;)
Там нет опции "Уведомлять при ответе". Это критично. Но в целом "жизнь" там живее, поэтому я и использую оба ресурса. Ты если что подскажи чайнику, может я местных обычаев просто не понимаю? Я восприму нормально, поверь...
Просто тут вот пост выше проскочил про умножение на 10 в степени... Вот я и думаю - если человек нормальный, взрослый, и не дурак, зачем так отвечать? Я ведь пост создал с одной мыслью - получить ответ, и оставаить этот пост чтобы другие могли почитать... А оказывается тут пальцев больше?
Вот ответь мне на один простой вопрос: Почему когда человек спрашивает "Как использовать колесо мыши в Дельфи?", я не отвечаю в "ироничном" стиле, а пишу прямо "Смотри события такие-то и такие-то"? Может я дурак? И чего-то не понимаю? Может правилом хорошего тона было бы как можно круче унизить спрашивающего? Написать что программирование не для него? Почему на этом сайте очень много подобных ответов? Ну разбираешься ты в предмете, неужели сложно или промолчать, или ответить по делу? Зачем нужно пытаться унизить собеседника, так и не ответив по сути?!?
Не могу понять... Может потому что я уже давно не мальчик? Лет уж слава Богу, 35 стукнуло... Или потому что я привык "за базар отвечать"? Что не помешало бы большинству отвечающих на вопросы новичков?
Я вот в своё время обучался некоторым м... скажем так - восточным единоборствам, и вот думаю... Вот встреть я этого автора "в тёмном переулке" - так ли он понтовался бы? Почему-то уверен что нет... Виртуал многое прощает...
Жалко мне. Хороший ресурс, но "правила" странноватые несколько, не находишь?
Вещь знания и умения - это не аксиома! Это то, чно каждый день нужно подтверждать! Не хочешь подтверждать? Ла не вопрос! Перестарь писать сюда или пользаваться подписью под ником "Специалист..." или "Динозавр...". Разве я не прав?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 12 авг 2007, 04:55

А это плохо? Почему не использовать ДВА ресурса? Там тоже много интересного бывает. Или это здесь "моветон", а sql.ru - "запретная зона" которую посещать "некомильфо"?
поскольку почти одни и те же отвечают на обоих ресурсах, задавать несколько вопросов лучше на одном из них. Я не запрещаю, просто лично мне почему-то не хочется отвечать на твой один вопрос здесь когда я вижу несколько других твоих же вопросов на sql.ru.
В плане тематики раздел на sql.ru и этот форум равны.
Просто тут вот пост выше проскочил про умножение на 10 в степени... Вот я и думаю - если человек нормальный, взрослый, и не дурак, зачем так отвечать? Я ведь пост создал с одной мыслью - получить ответ, и оставаить этот пост чтобы другие могли почитать... А оказывается тут пальцев больше?
сам пальцы загни. чего вас, новичков, всегда так непонравившиеся ответы возбуждают? Не понял - ну спроси еще.
А смысл в том, что константу-то можно записать, только ее надо сначала определить. для третьего диалекта FB один час это 1/23.99999. Почему не 1/24, и почему 5 девяток - читай про поддержку "больших чисел" в третьем диалекте. Кроме того на борланде есть документ про вычисления над датами и временем.
вот в своё время обучался некоторым м... скажем так - восточным единоборствам, и вот думаю... Вот встреть я этого автора "в тёмном переулке" - так ли он понтовался бы? Почему-то уверен что нет... Виртуал многое прощает...
гм, вот возьму, и отрублю за демагогию. Запомни раз и навсегда - на форумах нет демократии. Есть диктатура модераторов. Поэтому раз пришел - не выступай. То не ответили ему, то ответили не так...
Никто вас учить на форуме не обязан. А наиболее раздражающие вопросы это именно вопросы ликбеза. Которые должны решаться по нормальному следующим образом:
- посмотрел документацию
- почитал faql
- поискал на форумах (!)
- если не нашел ничего похожего (!) - задай вопрос.
Разве я не прав?
не прав. я себе придумал правило, и другим рекомендую.
Вот хочешь ты чего спросить или ответить. Нажми кнопочку, вбей текст.
Сотри его. Вбей еще раз, заново. Опять сотри. Если вопрос или ответ остался - введи третий раз и нажми отправить.

Kotъ-Begemotъ
Сообщения: 250
Зарегистрирован: 25 июл 2007, 21:33

Сообщение Kotъ-Begemotъ » 12 авг 2007, 13:19

kdv писал(а):Я не запрещаю, просто лично мне почему-то не хочется отвечать на твой один вопрос здесь когда я вижу несколько других твоих же вопросов на sql.ru
Ну я же совершенно разные вещи спрашиваю - там про одно тут про другое...

С остальным пожалуй соглашусь. За дельный совет спасибо :)

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Re: Работа с полями TimeStamp в FB

Сообщение stix-s » 13 авг 2007, 08:58

Slavik писал(а):
Kotъ-Begemotъ писал(а):Зная что минуте соответствует значение 0.000694444446708076 я и сделал запрос
А не проще умножать на 1440 (24*60)?
ммммм, а что есть 1440?

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 13 авг 2007, 09:56

kdv писал(а): А смысл в том, что константу-то можно записать, только ее надо сначала определить. для третьего диалекта FB один час это 1/23.99999. Почему не 1/24, и почему 5 девяток - читай про поддержку "больших чисел" в третьем диалекте. Кроме того на борланде есть документ про вычисления над датами и временем.
Так, побегу-ка я снова доку читать :) а то интервал между полями типа TIME вычислял, как разницу и считал, что получаю результат в секундах :)
Последний раз редактировалось stix-s 13 авг 2007, 10:13, всего редактировалось 1 раз.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 13 авг 2007, 10:05

stix-s писал(а):Так, побегу-ка я снова доку читать :) а то интервал между полями типа TIME вычислял, как разницу и считал, что получаю результат в секундах :)
Time и TimeStamp - совершенно разные вещи.

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 13 авг 2007, 10:14

WildSery писал(а):
stix-s писал(а):Так, побегу-ка я снова доку читать :) а то интервал между полями типа TIME вычислял, как разницу и считал, что получаю результат в секундах :)
Time и TimeStamp - совершенно разные вещи.
да, но береженого бог бережет, что-то было про то, что там еще миллисекунды приплетаются :)

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 13 авг 2007, 10:23

stix-s писал(а):да, но береженого бог бережет, что-то было про то, что там еще миллисекунды приплетаются :)
Они и там, и там есть.
Надо просто помнить, что current_time = current_time(0), а вот current_timestamp = current_timestamp(3).

Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Re: Работа с полями TimeStamp в FB

Сообщение Slavik » 13 авг 2007, 11:51

stix-s писал(а):ммммм, а что есть 1440?
Дык, это количество минут в сутках. Т.к. разница между двумя timestamp'ами получается в сутках, то чтобы получить эту разницу в часах, надо её умножить на 24, в минутах - ещё на 60 (24*60=1440).
kdv писал(а):для третьего диалекта FB один час это 1/23.99999. Почему не 1/24, и почему 5 девяток - читай про поддержку "больших чисел" в третьем диалекте.
А вот это для меня открытие. Перечитал статью про большие числа в третьем диалекте. Так и не понял, почему 1/23.99999, а не 1/24.00000, например.
kdv писал(а):Кроме того на борланде есть документ про вычисления над датами и временем.
Ссылочку можно? или название документа?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 авг 2007, 17:19


Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Сообщение Slavik » 20 авг 2007, 13:33

kdv писал(а):www.ibase.ru/develop.htm
Спасибо за ссылочку :). Я и раньше не брезговал туда захаживать, и сейчас пересмотрел статьи по теме. Особенно мне понравилась статья про математические операции с датами и временем с борланда. Всё, как я и посоветовал, не делить на приближённое число, а умножать на точное целое число часов, минут или секунд в сутках. Поэтому, ещё раз прошу объяснить мне, почему
kdv писал(а):для третьего диалекта FB один час это 1/23.99999. Почему не 1/24, и почему 5 девяток
??? Не могу никак врубиться! ](*,)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 20 авг 2007, 14:21

??? Не могу никак врубиться!
не можешь врубиться - попробуй.
select 1/24, 1/23.99999 from rdb$database.

проверь что будет в первом столбце и во втором.
Потом попробуй прибавить к этому current_timestamp.
и т.д.

Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Сообщение Slavik » 20 авг 2007, 17:10

kdv писал(а):не можешь врубиться - попробуй.
select 1/24, 1/23.99999 from rdb$database.
Попробовал. С 1/24 и так всё ясно -- округление до целого. А вот почему час в третьем диалекте FB равен 1/23.99999? и почему именно пять девяток, а не шесть? почему не 1/24.00000?. Попробовал следующее:

Код: Выделить всё

select 1/23.99999, 1/24.00000 from rdb$database
и был неприятно удивлён: результаты вычисления двух выражений идентичны при любом одинаковом количесте девяток и нулей от 1 до 9. При увеличении количества девяток более девяти точность 1/23.(9) падает, а вот точность 1/23.(0) с увеличением количества нулей только растёт вплоть до семнадцати нулей. С чем это связано?

Собственно вопрос Kotъ-Begemotъ'а был в другом, а именно в подсчёте кол-ва минут между двумя двумя timestamp'ами. И сколько я не экспериментировал, но чтобы получить точную разницу в часах, делить на (1/23.99999) или даже на (1/24.00000) нельзя, т.к. точность никудышняя. Гораздо проще и точнее умножать разницу между timestamp'ами на 24, что и советует Борланд.
kdv писал(а):Потом попробуй прибавить к этому current_timestamp.
и т.д.
Поэкспериментировал и с прибавкой к timestamp'у целого количества часов. Выяснил следующее.

Если к значению типа timestamp прибавлять h/23.(9) (где h - целое количество часов от 1 до 23), то точность вычислений растёт с увеличением количества девяток, и наилучший (но всё же не точный) результат достигается при девяти девятках, а дальше точность падает в полном соответствии с предыдущими изысканиями о точности вычисления 1/23.(9).

Если к значению типа timestamp прибавлять h/24.(0), до полная точность (совпадение десятых миллисекунд) достигается при десяти и более нулях после точки.

Также полная точность достигается, если прибалять h/cast(24 as double precision).

Вывод, для прибавления к timestamp'у одного часа в третьем диалекте FB, чтобы не парить себе мозги, надо добавлять 1/cast(24 as double precition), а не 1/23.99999 или даже 1/24.00000.

Кому интересно, тестовый блок:

Код: Выделить всё

execute block returns (Hours integer, TimeF varchar(30),
  Time1 varchar(30), Time2 varchar(30), Time3 varchar(30), Time4 varchar(30),
  Time5 varchar(30), Time6 varchar(30), Time7 varchar(30), Time8 varchar(30),
  Time9 varchar(30), Time10 varchar(30), Time11 varchar(30), Time12 varchar(30)
) as
  declare variable Today timestamp;
begin
  Hours = 0; Today = current_date;
  while (Hours < 24) do begin
    Hours = Hours + 1;
    -- Для краткости убираем дату из результата
    TimeF = cast(Today + Hours/cast(24 as double precision) as time);
    Time1 = cast(Today + Hours/24.0 as time);
    Time2 = cast(Today + Hours/24.00 as time);
    Time3 = cast(Today + Hours/24.000 as time);
    Time4 = cast(Today + Hours/24.0000 as time);
    Time5 = cast(Today + Hours/24.00000 as time);
    Time6 = cast(Today + Hours/24.000000 as time);
    Time7 = cast(Today + Hours/24.0000000 as time);
    Time8 = cast(Today + Hours/24.00000000 as time);
    Time9 = cast(Today + Hours/24.000000000 as time);
    Time10 = cast(Today + Hours/24.0000000000 as time);
    Time11 = cast(Today + Hours/24.00000000000 as time);
    Time12 = cast(Today + Hours/24.000000000000 as time);
    suspend;
  end
end
P.S. Для тестирования h/23.(9) заменить везде 24.0... на 23.9...

stix-s
Заслуженный разработчик
Сообщения: 557
Зарегистрирован: 13 дек 2005, 11:52

Сообщение stix-s » 21 авг 2007, 07:30

Код: Выделить всё

select (1/23.99999+current_timestamp), (1/24+current_timestamp) from rdb$database
А вот так ты получишь разницу в час :)

Slavik
Сообщения: 115
Зарегистрирован: 17 янв 2007, 11:52

Сообщение Slavik » 21 авг 2007, 09:49

ТАК ты НЕ получишь разницу в час. Для проверки, достаточно сконвертировать timestamp в varchar:

Код: Выделить всё

select cast((1/23.99999+current_timestamp) as varchar(30)), cast((1/24+current_timestamp) as varchar(30))
  from rdb$database

Пример результата выполнения запроса:

2007-08-21 09:45:08.9210 | 2007-08-21 08:45:09.4970
Согласись, что разницу между этими двумя значениями можно считать часом лишь приближённо на "бытовом" уровне :)

Ответить