информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Где водятся OGRыПортрет посетителя
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
непосретственно из запроса ты можешь ссылаться на переменную... 25.02.11 20:38  Число просмотров: 1611
Автор: Den <Denis> Статус: The Elderman
Отредактировано 25.02.11 20:41  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
непосретственно из запроса ты можешь ссылаться на переменную или объект формы, типа:
select * from list where list.date like Str(Year([frmMy]![editDate])) & "*"
или
select * from list where list.date like Str(DatePart("yyyy"), [frmMy]![editDate]) & "*"

еще можно строить запрос собираю строку в коде VB и записывать в свойство .SQL запроса:
myquery.sql = "select * from list where list.date like '" & Str(Year(Me.editDate.value)) & "*' "
<programming>
[SQL] Можно ли в SQL-запросе общащаться к перменной типа Date как к структуре? 24.02.11 08:19  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
Отредактировано 24.02.11 08:20  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Работаю в MS Ассеss. Есть таблица list (id, date, title). Поле date имеет тип «Полный формат даты» (например, 19.06.1994 17:34:23). Можно ли с помощью SQL-запроса выбрать записи с конкретным днём, месяцем или годом? Т.е. можно ли как-то исхитриться, чтобы заработал такой запрос: «SELECT * FROM list WHERE date.year = 1994»?

У меня есть идеи по поводу того, как решить эту задачи, но они громоздкие, хотелось бы найти что-нибудь попроще. Одна из идей – это перед выполнением запроса динамически генерировать временную таблицу, где под каждый параметр даты отводить отдельное поле и делать выборку уже из этой таблицы.
Как вариант, дату можно представить iso форматом (yyyymmdd... 24.02.11 14:43  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 24.02.11 14:44  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
Как вариант, дату можно представить ISO форматом (YYYYMMDD или YYYYMMDDhhmmss) в строке и работать как со строкой. Например:
select * from list where date like '1994%' -- YEAR
select * from list where date like '____06%' -- MONTH
select * from list where date like '______19%' -- DAY
Большое спасибо, с LIKE’ом действительно, получается то, что... 25.02.11 11:15  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Большое спасибо, с LIKE’ом действительно, получается то, что нужно (только в аксесе вместа знака % используется *, а вместо _ - ?). Вот только появилась новая проблема – каким образом формировать динамически нужный запрос?

Т.е. у меня есть две таблицы: list (id, date, title), years (id, title), Есть запрос «SELECT * FROM list WHERE date like '???12*';». Если я просто создам запрос обычными средствами Access и помещу туда данную строку, то всегда будет выполняться одно и то же.

Средствами Access можно в подчинённой форме указывать запрос, вот только я не понимаю, как передавать ему параметры. Допустим. есть форма-таблица со списком годов. Как сделать так, чтобы при нажатии на «+» управление передавалось в процедуру VBA, которая бы подставляла в LIKE соответствующую строку? Пробовал на разные события вешать обработчик, но что-то не получилось.

Если я сделаю такой запрос: «SELECT * FROM list WHERE date like mask», то как мне вовремя подставить нужное значение в переменную mask, чтобы не выпадало окошко для ввода параметра вручную?
непосретственно из запроса ты можешь ссылаться на переменную... 25.02.11 20:38  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 25.02.11 20:41  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
непосретственно из запроса ты можешь ссылаться на переменную или объект формы, типа:
select * from list where list.date like Str(Year([frmMy]![editDate])) & "*"
или
select * from list where list.date like Str(DatePart("yyyy"), [frmMy]![editDate]) & "*"

еще можно строить запрос собираю строку в коде VB и записывать в свойство .SQL запроса:
myquery.sql = "select * from list where list.date like '" & Str(Year(Me.editDate.value)) & "*' "
Что-то не получается. пищу: «select * from list where date... 01.03.11 10:58  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Что-то не получается. Пищу: «SELECT * FROM list WHERE date Like '??????' & Str(year!title);». Форма открывается, запрос выполняется, editbox из формы year!title видит (окошко с запросом ввода переменной не выскакивает), но запрос возвращается пустым. Если вручную вместо «Str(year!title)» подставить, например, ‘2000’, то запрос выполняется адекватно. Что я делаю не так.

Ещё по второму случаю вопрос. Не совсем понятна последовательность действий. Вот у меня есть родительская форма… А дальше не понятно, что делать. Когда запрос уже есть всё ясно – создаём подчинённую форму и связываем её с этим запросом, а в случае, если я динамически запрос создаю, то что делать после создания родительской формы? Если подчинённую форму создавать, то что ей в источник записей ставить, а если этот динамически сформированный запрос записывать в реально существующий, то по какому событию это делать? Я пытался методом тыка события перебрать, чтобы до выполнения запроса вклиниться, но что то так и не нашёл нужного.
Ещё меня интересует, как непосредственно из VB с запросами... 02.03.11 14:11  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Ещё меня интересует, как непосредственно из VB с запросами работать. Полный вопрос в верхнем сообщении. В бейсике хоть отладку можно вести, можно увидеть, что там в запросе получилось...
Например так: 02.03.11 23:36  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 02.03.11 23:39  Количество правок: 4
<"чистая" ссылка> <обсуждение закрыто>
Например так:
Dim qryMy as QeryDef
Set qryMy = CurrentDatabase.QueryDefs("MyQuery")
With qryMy
  .SQL = "SELECT *" & vbNewLine & _
    "  FROM List" & vbNewLine & _
    "  WHERE timestamp >= #01.01." & CStr(Year(Now())) & "#" & vbNewLine & _
    "    AND timestamp < #01.01." & CStr(Year(Now())+1) & "#"
End With

---

P.S. вместо CurrentDatabase нужно использовать то, что рекомендуется для конкретной версии Access и конкретного типа проекта. F1 тебе в помощь!
"select * from list where date like '??????" &... [upd] 01.03.11 12:02  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 01.03.11 12:30  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
"SELECT * FROM list WHERE date Like '" & Str(year!title) & "????'"

если date в формате YYYYMMDD
Я для простоты текстовое поле обычное сделал, но не работает. 01.03.11 13:09  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Моя ошибка. в VB надо использовать функцию CStr, а не Str [upd] 01.03.11 13:44  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 01.03.11 23:33  Количество правок: 3
<"чистая" ссылка> <обсуждение закрыто>
SELECT * FROM List WHERE List.date Like CStr(Year([formSelect]![editDate])) & '????';

Очень рекомендую хранить дату в строке именно в ISO формате, чтобы быстрее работало упорядочивание по дате с использованием индекса.
Попробовал последовать вашей рекомендации, и совершенно... 02.03.11 14:08  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Попробовал последовать вашей рекомендации, и совершенно запутался. Не представляю, как запрос отлаживать, чтобы посмотреть, что там за строка для LIKE'а получилась. Вы говорите про ISO-формат. Я поменял тип поля tile вместо строки на краткий формат даты, например, 01.01.1900. Но если это уже не строка, то в каком виде оно доходит до запроса? Со строкой хоть можно было предсказуемый результат получить, а тут вообще непонятно, что в LIKE для примера вписывать. Например, 01.01.1900 в каком виде доходит? 01011900, 19000101 или что-то ещё?

PS. С CStr тоже не работает.

PPS. А если я не строкой, а числом буду иднекс по годам делать?Это же тоже должно быстро работать? Зачем мне дни и месяцы в иднексе, где только год нужен.
оператор LIKE проверяет строковое выражение (символьное поле... 02.03.11 23:16  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 03.03.11 14:41  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
> Попробовал последовать вашей рекомендации, и совершенно
> запутался. Не представляю, как запрос отлаживать, чтобы
> посмотреть, что там за строка для LIKE'а получилась. Вы
> говорите про ISO-формат.

оператор LIKE проверяет строковое выражение (символьное поле таблицы) на совпадение заданному шаблону.

> Я поменял тип поля tile вместо
> строки на краткий формат даты, например, 01.01.1900. Но
> если это уже не строка, то в каком виде оно доходит до
> запроса?

Ни в каком. Некоторые БД работают с датой как со строкой, но в случае Access, это врядли получится.

> Со строкой хоть можно было предсказуемый результат
> получить, а тут вообще непонятно, что в LIKE для примера
> вписывать. Например, 01.01.1900 в каком виде доходит?
> 01011900, 19000101 или что-то ещё?

если решил использовать формат даты, то можно воспользоваться советом kstati и использовать оператор between. Но если предполагается использовать только выборку за год, то проще использовать >= и <
Например
WHERE list.timestamp >= #01.01.2010# AND list.timestamp < #01.01.2011#
проще некуда и приобразовывать ничего не надо.

> PS. С CStr тоже не работает.

Функция СStr() всего лишь приобразовывает данные числового формата в строку.

> PPS. А если я не строкой, а числом буду иднекс по годам
> делать?Это же тоже должно быстро работать? Зачем мне дни и
> месяцы в иднексе, где только год нужен.

а смысл? я до сих пор не могу понять цели всех этих манипуляций. ты скажи - что в итоге надо получить?
в таком случае используй between. В запросах с like и функциями типа Year по дате приходится смотреть все кортеджи, ибо, как ты и сказал "это уже не строка" - приходится производить преобразование даты в строку, затем сравнивать like, 02.03.11 14:19  
Автор: kstati <Евгений Борисов> Статус: Elderman
Отредактировано 02.03.11 14:21  Количество правок: 3
<"чистая" ссылка> <обсуждение закрыто>
Не знаю, есть ли это в убогом Аксессе, но в MySQL есть... 24.02.11 09:21  
Автор: Winer <Виктор С.> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> Работаю в MS Ассеss. Есть таблица list (id, date, title).
> Поле date имеет тип «Полный формат даты» (например,
> 19.06.1994 17:34:23). Можно ли с помощью SQL-запроса
> выбрать записи с конкретным днём, месяцем или годом? Т.е.
> можно ли как-то исхитриться, чтобы заработал такой запрос:
> «SELECT * FROM list WHERE date.year =
> 1994»?

Не знаю, есть ли это в убогом Аксессе, но в MySQL есть оператор BETWEEN. С его помощью ты сможешь выбрать записи от 01.01.1994 00:00:00 до 31.12.1994 23:59:59
Вообще-то в MySQL это делается по другому ) и гораздо изящнее: 24.02.11 11:05  
Автор: Fighter <Vladimir> Статус: Elderman
Отредактировано 24.02.11 11:06  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> > Работаю в MS Ассеss. Есть таблица list (id, date,
> title).
> > Поле date имеет тип «Полный формат даты» (например,
> > 19.06.1994 17:34:23). Можно ли с помощью SQL-запроса
> > выбрать записи с конкретным днём, месяцем или годом?
> Т.е.
> > можно ли как-то исхитриться, чтобы заработал такой
> запрос:
> > «SELECT * FROM list WHERE date.year
> =
> > 1994»?
>
> Не знаю, есть ли это в убогом Аксессе, но в MySQL есть
> оператор BETWEEN. С его помощью ты сможешь выбрать записи
> от 01.01.1994 00:00:00 до 31.12.1994 23:59:59
Вообще-то в MySQL эт оделается по другому )
SELECT * FROM list WHERE YEAR(`date`)='1994'
где YEAR() - функция, возвращающая номер года той даты, которую ей скормили. Есть еще функции DAY() и MONTH(), если нужно.
Неоптимальное с точки зрения индекса решение, если я не... 24.02.11 12:15  
Автор: Winer <Виктор С.> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> > Не знаю, есть ли это в убогом Аксессе, но в MySQL есть
> > оператор BETWEEN. С его помощью ты сможешь выбрать
> записи
> > от 01.01.1994 00:00:00 до 31.12.1994 23:59:59
> Вообще-то в MySQL эт оделается по другому )
> SELECT * FROM list WHERE YEAR(`date`)='1994'
> где YEAR() - функция, возвращающая номер года той даты,
> которую ей скормили. Есть еще функции DAY() и MONTH(), если
> нужно.

Неоптимальное с точки зрения индекса решение, если я не ошибаюсь. Надо перелопатить все строки с применением к ним функции и сравнить с необходимым значением. В случае BETWEEN, если я не ошибаюсь, индексы нормально задействуются.
Отнюдь ) при использовании between индексы используюся активно. Кстати говоря напоминаю, что есть очень удобный инструмент анализа запросов. имя ему `describe` ;)[upd] 01.03.11 23:06  
Автор: kstati <Евгений Борисов> Статус: Elderman
Отредактировано 02.03.11 01:15  Количество правок: 14
<"чистая" ссылка> <обсуждение закрыто>
Одна из задач индексов - быстрая сортировка значений для выборки.
В случае использования between по индексированному полю идёт поиск малого значения, затем выдача результата вплоть до большего значения.

Выгода очевидна, по скорости. А причина - количество затрагиваемых строк (в моём случае 30480 против 762707), которые обусловлены типом запроса range и index соответственно; При этом вариант "where YEAR(`d`) " даже не пытается использовать ключи.

Теста ради набил таблицу хламом - случайными датами за 50 лет:

insert into tests.date_test values (NOW() - interval floor(rand()*365*50) day);

А за тем выбрал данные за 2001 год.
Если работа ведётся именно с диапазоном, то between рулит. Ясное дело, если нужно выбрать к примеру все первые числа, то ой )

mysql> describe date_test;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| d     | date | YES  | MUL | NULL    |       |
+-------+------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> select distinct count(*) from date_test;
+----------+
| count(*) |
+----------+
|   762061 |
+----------+
1 row in set (0.77 sec)



mysql> select count(*) from date_test where YEAR(`d`) = 2001;
+----------+
| count(*) |
+----------+
|    15401 |
+----------+
1 row in set (0.80 sec)

mysql> select count(*) from date_test where `d` like "2001%";
+----------+
| count(*) |
+----------+
|    15401 |
+----------+
1 row in set, 1 warning (0.84 sec)

mysql> select count(*) from date_test where  `d` between '2001-01-01' and '2001-12-31';
+----------+
| count(*) |
+----------+
|    15401 |
+----------+
1 row in set (0.02 sec)


mysql> describe select count(*) from date_test where  `d` between '2001-01-01' and '2001-12-31';
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows  | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | date_test | range | i             | i    | 4       | NULL | 30480 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
1 row in set (0.00 sec)

mysql> describe select count(*) from date_test where YEAR(`d`) = 2001;
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows   | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | date_test | index | NULL          | i    | 4       | NULL | 762707 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+

mysql> describe select count(*) from date_test where `d` like "2001%";
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows   | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | date_test | index | i             | i    | 4       | NULL | 762707 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
1 row in set, 1 warning (0.00 sec)


---
[upd] Как и ожидал between даёт эффект и при работе с or.
То есть поиск данных за определённый месяц тоже работает на ура, хотя выгода по времени уже не на столько заметна.

<?
$sql = "select count(*) from date_test where  ";
$tmp = array();
for ($i=1961; $i<=2011; $i++) {
$tmp[] = "`d` between '$i-01-01' and '$i-01-31'";
}
$sql .= join(" or ", $tmp);
?>

---

Преобразуется в длиннющий запрос:
select count(*) from date_test where  `d` between '1961-01-01' and '1961-01-31' or ... or `d` between '2011-01-01' and '2011-01-31

select count(*) from date_test where  `d` between '1961-01-01'....<откусил>
+----------+
| count(*) |
+----------+
|    64615 |
+----------+
1 row in set (0.45 sec)


mysql> describe select count(*) from date_test where  `d`...<откусил>
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows  | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | date_test | range | i             | i    | 4       | NULL | 64566 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+-------+--------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from date_test where d like __01%';
+----------+
| count(*) |
+----------+
|    64615 |
+----------+
1 row in set, 1 warning (0.92 sec)
mysql> describe select count(*) from date_test where d like __01%';
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows   | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | date_test | index | NULL          | i    | 4       | NULL | 762561 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+--------+--------------------------+
1 row in set, 1 warning (0.00 sec)

---

В общем, не стоит отмахиваться от between ) реально удобно и быстро.
И, кстати, если внимательно приглядеться к выборке длиннющим запросом, то количество затрагиваемых тестами строк меньше чем количество результирующих строк. Сильно копошиться ломает, но предполагаю, что дело в бинарном поиске.
Ага, таки сильно ошибался я, а не Winer 02.03.11 00:31  
Автор: Fighter <Vladimir> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Насколья помню - очень сильно ошибаешся. Нынешний мускул неоптимизирован только для OR 24.02.11 18:02  
Автор: Fighter <Vladimir> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Это всё хорошо, но в Access'ом SQL'е данная комбинация не работает. 24.02.11 11:32  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
1  |  2 >>  »  




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach