Rambler's Top100
Форум: MS ACCESSVBVBA MS OfficeMS SQL server
Новые сообщения: 0000

Форум: MS ACCESS

Вопросы связанные с MS ACCESS

Обновить визитку
Участники «Online»
Все участники

 
 

Доброго времени суток, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: автонумерация строк в запросе (с небольшим подковыром)
 
 автор: Explorer   (04.03.2007 в 03:30)   личное сообщение
 
 

много сломано копий вокруг такой задачи как указание фэйкового (Fake) порядкового номера записи для номерации строки запроса. Во всех специализированных форумах гуру разработки приложений БД постоянно подтрунивают над новичками.

<skiped>

в общем количество аргументов говорящих не в пользу таких решений весьма велико, тем не менее в ряде случаев такая нумерация просто необходима и весьма удобна.

предположим (может излишне смелое предположение, но для меня регулярная ежедневная задача) у вас есть файл EXCEL содержащий 2-7-10'000 записей о событиях - на листе по порядку перечислены:


   DATE   |   PLACE   |   RATE
----------+-----------+----------
 12/09/06 |   1       |   1.00
 12/09/06 |   0       |   1.07
 12/09/06 |   3       |   1.88
 17/09/06 |   0       |   1.00
 17/09/06 |   2       |   1.13
 18/09/06 |   1       |   1.43
 19/09/06 |   4       |   1.99
 19/09/06 |   1       |   1.75
 19/09/06 |   0       |   1.08
 19/09/06 |   2       |   1.03
 19/09/06 |   3       |   1.56
 20/09/06 |   1       |   1.98
 20/09/06 |   0       |   1.77


для документа Excel таая структура вполне нормальна - последовательность события определяется порядком записи. Имея такую таблицу легко расчитать, например сумму с накопленным итогом или среднее отклонение коэффициента на дату или накопленный результирующий коэффициент на дату или на каждое следующее событие (сумма нарастающим итогом например)

при чем в Excel это решается легко и непринужденно - там к предыдущей ячеке можно обратиться явно, чего не скажешь про решение в Access - сто вопросов в форумах - как посчитать значение "Текущая запись" + "Предыдущая запись"? а если нарушен порядок сортировки? а если в таблице есть пропущенные значения?

Кроме того, и об этом новичкам говорят постоянно - принцип хранения и сортировки данных в Access и в Excel (в DataBase и SpreadSheet) совершенно различен - и то, что кажется само собой разумеющимся в одном случае не будет работать или даст неверный результат в другом - будет нарушена последовательность счетчика при пересортировке, например, или Агрегатные функции вообще не будут работать...

в некоторых случаях можно сначала экспортировать даные из Excel в таблицы Access одновременно присваивая им идентификаторы или уже после экспорта данных модифицировать таблицу Access добавив поле счетчика (это совершенно разные подходы) записи получат уникальный идетификатор и с ними можно будет работать точно так как с любыми другими массивами данных в Acces обращаясь к полям записи в запросе.

но это может оказаться слишком хлопотно и громоздко - какой смысл экспортировать данные, если нужно всего три секунды на то, чтобы их обработать, агрегировать, извлечь информацию и выкинуть. (даже не упоминая о потоянно пухнущей при этих операциях базе - которую придется постоянно сжимать и сбрасывать счетчики Autoincrement).
А если в исходной таблице 65536 записей? например данные за 10 лет всего по 10 событий на каждый день, займут 36500 строк в таблице Excel

но можно и не импортивать данные а просто прилинковать таблицы Excel и нумеровать сроки уже в запросе основанном на такой прилинкованной таблице - при этом порядок сортировки (последовательность записей) будет всегда остваться той, что задана в файле Excel.

на примере приведенных выше данных - допустим вам нужно присвоить порядковый номер событиям перечисленным в таблице Excel. Последовательно +1 в пределах каждого одного дня, со сбросом счетчика каждый новый день


 COUNTER |   DATE   |   PLACE   |   RATE
---------+----------+-----------+----------
  1      | 12/09/06 |   1       |   1.00
  2      | 12/09/06 |   0       |   1.07
  3      | 12/09/06 |   3       |   1.88
  1      | 17/09/06 |   0       |   1.00
  2      | 17/09/06 |   2       |   1.13
  1      | 18/09/06 |   1       |   1.43
  1      | 19/09/06 |   4       |   1.99
  2      | 19/09/06 |   1       |   1.75
  3      | 19/09/06 |   0       |   1.08
  4      | 19/09/06 |   2       |   1.03
  5      | 19/09/06 |   3       |   1.56
  1      | 20/09/06 |   1       |   1.98
  2      | 20/09/06 |   0       |   1.77


если просто экспортировать данные в Access, то при пересортировке таблицы может нарушиться последовательность событий и, например, расчеты основанные на данных предыдущих приодов окажутся выполненными некорректно.

если предварительно подготавливать данные в таблице Excel - можно легко ошибиться - неверно указать номер, пропустить дату и не сбросить счетчик номера в "1"

Но если просто прилинковать таблицу Excel и используя ее в качестве источника строк, выполнить нехитрый запрос, вида (пример):

SELECT 
LINKED.DATE, numerate([DATE]) AS COUNTER, LINKED.PLACE, LINLKED.RATE
FROM LINKED
WHERE (((LINKED.DATE) IS NOT NULL) AND ((firstnum())=TRUE))
ORDER BY LINKED.DATE, COUNTER;


обращающийся к PUBLIC функциям нумерации, вынесенными в отдельный модуль basNumerate
в декларациях модуля должны быть объявлены переменные:


Option Compare Database
Option Explicit

Private curNum As Long - текущее значение счетчика
Private curDate As Date - текущее значение даты


функция numerate (получает в качестве аргумента значение даты текущей записи из запроса):


Public Function numerate (DATE As Date) As Long

If curDate <> DATE Then 'проверяем равна ли дата предыдущей
    curNum = 1 ' если нет начинаем считать COUNTER с "1" - т.е. новый или первый день
Else
    curNum = curNum + 1 ' если дата равна предшествующей (тот же день) увеличиваем счетчик на "1"
End If

    COUNTER = curNum - записываем значение счетчика
    curDate = ActionDate - запоминаем значение даты
  
End Function

функция firstnum (вспомогательная функция в условии WHERE нужна для того, чтобы зайти в каждую запись - не возвращает данных в запрос)


Public Function firstnum() As Boolean
    firstnum = True
End Function


пронумеровав таким образом записи в запросе для расчетов,

можно будет применять все инструменты Access, в том числе агрегатные функции (SUM, AVG) и агрегатные функции домена (DLOOKUP, DMIN), обращаясь к записи по ее идентификатору (COUNTER & DATE дадут уникальный идентификатор записи)

если не использовать проверку на дату и не переустанавливать счетчик в "1" то такого рода запрос пронумерует все записи подряд - в той последовательности как они идут в таблице Excel.

работает достаточно быстро

  Ответить  
HiProg.com - Технологии программирования
Rambler's Top100 TopList