![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Отбор по дате [MSSQL]
Link © (2002-08-23 14:03:00)Уважаемые мастера! Только щас дошло, что следующий запрос отбирает не записи, созданные до определённой даты, а записи, существующие в промежутке между указанными днями каждого месяца. (Если я не прав, скажите мне) То есть некоторые записи выпускаются.
Help!!!!
Совершенно не представляю как сделать , чтобы отбирались записи, созданные до указанной даты. Подскажите, пожалуйста.
Запрос:
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE (DATEPART(dd, CAST(timestamp AS datetime))between :ddStart and :ddEnd)
and (DATEPART(mm, CAST(timestamp AS datetime))between :mmStart and :mmEnd )
and recv>0;
--and sent > 0
Link (2002-08-24 09:31:00) [1]
> MOA
Спасибо за помощь!
Оказалось, что я не правильно записываю значение даты, а нужно так 02/31/12 23:12:21 и ещё в другом запросе не было скобок. И из-за этого не получалось!!!! Бывает же так, а сколько нервов...
Ну теперь-то всё работает :)
Спасибо всем за советы и поддержку! :)
MOA (2002-08-23 17:58:00) [2]>выдаёт меньше ошибок
Странно ;), у меня запрос работает без ошибок (копировал прямо из аналайзера). А текст ошибки - по русски?
> как это написать, если только одна переменная, где одна дата, содержащая год, месяц, день, час
Пишем в TQuery (или TADOQuery):
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE ([timestamp] between :StartDate and :EndDate)
and (recv>0)
В параметрах появятся параметры StartDate и EndDate с типом ftDateTime. Присваиваем нужные значение и все. Вот пока писал, сделал у себя -все работает.
Удачи!
Link (2002-08-23 17:40:00) [3]
> SergSuper
Просто в твой первый код нельзя добавить MINUTE и SECOND, пишет, что такого не бывает.
> лучше передавать не кучу параметров(год, месяц, день, час),
> а одну дату, для этого и существует соответствующий тип.
Тогда, будь другом, скажи, как это написать, если только одна переменная, где одна дата, содержащая год, месяц, день, час.
А то я уже запарился... :
SergSuper (2002-08-23 17:32:00) [4]2 Link
Если не знаешь как быть с минутами и секундами - значит не дошло :)
Можно еще переделать метод MOA
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE timestamp
BETWEEN dateadd(yy, :yyStart-2000, dateadd(mm,dateadd(mm, :mmStart-1,dateadd(dd, :ddStart-1,dateadd(mi, :miStart, dateadd(hh, :hhStart,"20000101")))))
and dateadd(yy, :yyEnd-2000, dateadd(mm,dateadd(mm, :mmEnd-1,dateadd(dd, :ddEnd-1,dateadd(mi, :miEnd, dateadd(hh, :hhEnd,"20000101")))))
Но всё это тупиковый путь, извращения даже (в том числе и что я предложил) - лучше передавать не кучу параметров(год, месяц, день, час), а одну дату, для этого и существует соответствующий тип.
Link (2002-08-23 17:16:00) [5]
> SergSuper
Боюсь ты опоздал :) это-то до меня уже дошло, но как же быть с секундами и минутами!!
> MOA
Я чуть-чуть переделал твой код
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE timestamp
BETWEEN CAST(CAST(:ddStart AS NCHAR(2))+"."+CAST(:mmStart AS NCHAR(2))+"."+CAST(:yyStart AS NCHAR(4))+" "+CAST(:miStart AS NCHAR(2))+":"+CAST(:hhStart AS NCHAR(2)) AS datetime)
AND
CAST(CAST(:ddEnd AS NCHAR(2))+"."+CAST(:mmEnd AS NCHAR(2))+"."+CAST(:yyStart AS NCHAR(4))+" "+CAST(:miEnd AS NCHAR(2))+":"+CAST(:hhEnd AS NCHAR(2)) AS Datetime)
Так выдаёт меньше ошибок :) но всё равно говорит, что "Приложение использует для текущей операции значение не верного типа" может ты знаешь в чём дело?
SergSuper (2002-08-23 16:56:00) [6]DmitryK, интересно а если бы я на 100 умножал как бы Вы объяснили?
Дело в следующем.
Если у нас только даты - то всё понятно. Но если есть месяц, то получается что мы в первую очередь должны учесть его. Мы должны придать месяцу какой-то вес, причем в любом случае он должен быть больше чем любой день. Для этого и умножаем на 31. На самом деле можно не на 31, а на любое число, большее чем количество дней в месяце.
Если не понятно то можно воспользоваться аналогией с десятичными числами: число 45 можно представить ведь как 4*10+5. И сравнивать с числом 64, представленном в виде 6*10+4. Но сравнение будет корректно если мы будет умножать не на 10, а на любое другое большее число: 4*100+5 < 6*100+4.
Если мы рассматривает 5-е апреля(05/04), то мы его можем представать как 4*31+5. Можно еще учитывать год - но это я оставляю как домашнее заданее :)
Link (2002-08-23 16:07:00) [7]
> DmitryK
Дошло! ..Бывают в жизни неудачи :))
> MOA
Щас попробую..
DmitryK (2002-08-23 16:03:00) [8]2Link
> что значит 31?
неужели так и не догодался?
31 - это количество дней в месяце. :)
MOA (2002-08-23 16:03:00) [9]Только сейчас понял, что под ddStart и ddEnd Link имел в виду именно день. Прошу прощения - не понял вопрос. Я имел в виду , что ddEnd и ddStart - это даты (типа datetime). Тогда можно примерно вот так
[timestamp]
BETWEEN CAST(CAST(yyStart AS NCHAR(4))+"-"+CAST(mmStart AS NCHAR(2))+"-"+CAST(ddStart AS NCHAR(2))+" "+CAST(minStart AS NCHAR(2))+":"+CAST(secStart AS NCHAR(2)) AS datetime)
AND
CAST(CAST(yyEnd AS NCHAR(4))+"-"+CAST(mmEnd AS NCHAR(2))+"-"+CAST(ddEnd AS NCHAR(2))+" "+CAST(minEnd AS NCHAR(2))+":"+CAST(secEnd AS NCHAR(2)) AS Datetime)
но лучше, конечно, на клиенте сформировать готовые параметры типа datetime и передавать уже их, как справедливо указал DmitryK.
Link (2002-08-23 15:55:00) [10]Всё-таки, здесь
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE DAY(timestamp)+MONTH(timestamp)*31
between :ddStart + :mmStart*31 and :ddEnd + :mmEnd *31
and recv>0;
--and sent > 0
что значит 31? И как быть с минутами и секундами?
Link (2002-08-23 15:39:00) [11]А вообще можно так писать MINUTE(timestamp)+SECOND(timestamp)?
Link (2002-08-23 15:33:00) [12]Мне нужно ещё ограничивать по минутам и секундам.
> SergSuper
К стати, как это получится
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE DAY(timestamp)+MONTH(timestamp)+MINUTE(timestamp)+SECOND(timestamp)*31
between :ddStart + :mmStart+:hhStart+:miStart*31 and :ddEnd + :mmEnd +:hhEnd+:miEnd*31
and recv>0;
--and sent > 0 ????
Всё таки не доходит, 31 - это что? дни?
DmitryK (2002-08-23 15:12:00) [13]но я думаю лучше не мудохаться с переходами от даты к числу и потом обратно, лучше искать непосредственно от указанной даты - до указанной даты
объясни, почему ты не хочешь(не можешь) воспользоваться столь удобным способом ограничить выборку????????
DmitryK (2002-08-23 15:07:00) [14]2Link
все именно так, как ты говоришь, твой запрос выбирает все записи между указанными номерами дней, во всех месяцах между указанными номерами месяцев.
в исходной форме ты бы должен был построить ограничение следующим образом
((месяц>=mmStart AND день>=ddStart) OR (месяц>mmStart)) AND
((месяц<=mmEND AND день<=ddEnd) OR (месяц<mmEnd))
(кажется так, но на всякий случай перепроверь - построй таблицу истинности)
Link (2002-08-23 14:58:00) [15]
> MOA
Извини не знаю, но, к сожалению переименовывать уже поздно, придётся много чего другого переписывать...
MOA (2002-08-23 14:56:00) [16]Забыл. Если (Link (23.08.02 14:32) timestamp типа datetime, то CAST зачем? Просто
[timestamp] between :ddStart and :ddEnd
И опять же поле timestamp не типа timestamp - это все-же приключения.
Удачи!
Link (2002-08-23 14:56:00) [17]
> SergSuper
Всё получилось, огромное тебе спасибо!
Но я с базами данных работаю недавно, тем более с запросами. Если тебе не сложно, объясни откуда взялась 31 и почему ты это всё складываешь...
Может тебе это и очевидно, тоды я бы хотел, чтобы и мне...
В любом случае спасибо!
MOA (2002-08-23 14:51:00) [18]Никак не могу сообразить, а почему же просто
(CAST(timestamp AS datetime) between :ddStart and :ddEnd)
не работает? И опять же, если timestamp имеет тип datetime, лучше его переименовать, если есть такая возможность.
SergSuper (2002-08-23 14:44:00) [19]а можно и короче
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE DAY(timestamp)+MONTH(timestamp)*31
between :ddStart + :mmStart*31 and :ddEnd + :mmEnd *31
and recv>0;
--and sent > 0
ну в принципе и еще есть варианты
SergSuper (2002-08-23 14:37:00) [20]дык проще надо, это же очевидно
select timestamp,src_IP,dst_IP,sent,recv from traffic_USER
WHERE DATEPART(dd, CAST(timestamp AS datetime))+DATEPART(mm, CAST(timestamp AS datetime))*31
between :ddStart + :mmStart*31 and :ddEnd + :mmEnd *31
and recv>0;
--and sent > 0
по хорошему еще бы и год надо учесть
Кстати мне не нравится конструкция CAST(timestamp AS datetime). Вы осознанно её используете?