Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > как получить значения поля без перебора по запросу


Автор: Lunatikus 10.9.2007, 12:36
Здравствуйте.Подскажите,пожалуйста,кто знает,как после ADOQuery.open получить все значения какого-то поля списком или массивом(чтобы значения шли в строгой последовательности как выдает запрос ADOQuery)?И возможно ли это?Просто перебор 1млн. записей с помощью next затормаживает.А перебор именно для считывания этих значений и на их основе вычисления новых для последующего апдейта таблицы в базе.База MS SQL Server 2000

Автор: Savek 10.9.2007, 12:44
Вряд ли, да и чем массив или список лучше RecordSet-a? 

Автор: Lunatikus 10.9.2007, 13:01
чем лучше,не знаю,не работал с рекордсетом.Какие методы мне надо знать,чтобы получить любое значение любого поля,зная его номер внутри рекордсета?Еще увидел,что у него,Как и у, ADOQuery етсь понятие текущей записи(если бы из адоквери можно было вытащить значение не текущей и я бы это знал,я бы не парился со списком отдельным).Каким образом ее передвигать?Спасибо за помощь =)

Автор: ZeroMem 10.9.2007, 13:59
Используй компоненты EhLib MemTable. Там можно указать свойство загружать ВСЕ(!!!) в массив, а потом достаточно просто получить к нему доступ. Вот только кажется там каждый элемент будет типа Variant... кажется. А вообще куском лучше не грузить. Лучше попробовать кусками этим же компонентом тягать данные.

Автор: Lunatikus 10.9.2007, 14:26
представь себе хотя бы 10 полей типа врачар(255) в миллион строк...и все это вариант...

Автор: Savek 10.9.2007, 15:18
Цитата(Lunatikus @  10.9.2007,  13:01 Найти цитируемый пост)
бы из адоквери можно было вытащить значение не текущей и я бы это знал,я бы не парился со списком отдельным).Каким образом ее передвигать?


First;
Last;
Next;
Prior;
MoveBy;
Locate;
lookup;
FindFirst;
FindNext;
.. и т.д.

Если работаешь с базами данных про массивы забудь! Опиши подробнее задачу попробуем найти правильное решение 

Автор: Lunatikus 10.9.2007, 15:38
задача уже решена,но выполнение процеса занимает три часа минимум.А все почему?Ситуация примерно такая,без улсожнений:
представьте календарь и несколько артикулов(товаров).ДЛя каждого артикула свой календарь,В котором ко дню привязан определенный остаток,прогноз(получается в минус остатка текущего),заказ(тоже в минус остатку),приход товара(в плюс).На основе этих полей надо просчитать остатки будущих дней(прогноз,заказы и приходы будущих дней известны и известен остаток на текущий день).Как я делал?В лоб.Я перебирал записи последовательно,сохранял остаток в переменную.Вычитал из нее значения из следующей записи и так далее....загрузка произошла изза того,что я каждый такой шаг выполняю запрос на запись в базу полученного остатка.А правильнее надо было бы делать один запрос в конце.Но тогда надо расчитать остатки программно опять же перебором,чтобы узнать значения поля остатка.Потому и хочу получить сразу весь список значений,чтобы работать с ним,а не использовать next,ибо это зло

Автор: Savek 10.9.2007, 15:54
Цитата(Lunatikus @  10.9.2007,  15:38 Найти цитируемый пост)
Я перебирал записи последовательно,сохранял остаток в переменную

Не совсем понятен алгоритм, но думаю этот перебор можно заменить одним запросом (знать бы структуру таблиц)

Автор: Lunatikus 10.9.2007, 16:08
никаких таблиц.Есть запрос,результат которого-этот самый календарь на все артикулы:
---data-----------articul----ostatok----prognoz----zakaz---prihod---
01.01.2007          A1           10              1               0            0
02.01.2007          A1           NULL          1               1            10
03.01.2007          A1           NULL          1               0            0

01.01.2007          A2           15              2               2            0
02.01.2007          A2           NULL          2               0            0
03.01.2007          A2           NULL          2               0            4

01.01.2007          A3           5                1               0            0
02.01.2007          A3           NULL          1               1            0
03.01.2007          A3           NULL          1               0            3
примерно это выдает запрос.И вот в этом наборе данных и перебираю по одной строке,считаю остаток следующей строки,записываю его апдейтом.Смещаюсь вниз,снова считаю...вот так  smile 
елси бы я знал сразу все значения всех этих полей и мог к каждому элементу мгновенно доступиться,было бы проще и рациональнее.Но,увы,я не знаю другого метода,кроме как вот так,перебором с next'ом

Автор: Savek 10.9.2007, 16:58
Цитата(Lunatikus @  10.9.2007,  16:08 Найти цитируемый пост)
Есть запрос,результат которого-этот самый календарь на все артикулы:

Т.е это промежуточное состояние данных? Здесь нужно плясать от того что мы имеем к тому что должны получить, возможно этот запрос не самый оптимальный. 

Автор: ALeXandrK 10.9.2007, 17:15
А почему бы тебе в твой запрос не добавить стрку INSERT INTO temp,
чтобы этот запрос превратился в таблицу, а потом, соответственно, 
следующим запросом подсчитать тебе все, что нужно и удалить
временную таблицу?!

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

Автор: SergeBS 11.9.2007, 07:46
Lunatikus, 
К Delphi твои проблемы не относятся. Прочитай Грабера(Грубера) про SQL или в BOL. Есть такая штука: агрегатные функции. Например:
Код

select sum(ostatok) as sum_ostatok where articul = A1

Догадайся, что эта строка вычислит smile

ALeXandrK, 
Цитата

Богат ни тот, у кого много, а тот, кому хватает

Не "ни тот", а "нЕ тот"!

Автор: Akella 11.9.2007, 08:09
Цитата(Lunatikus @  10.9.2007,  15:38 Найти цитируемый пост)
Ситуация примерно такая,без улсожнений:

а ты это всё на клиенте считаешь? А если алгоритм перевести в хранимку и считать на сервере.... это значительно ускорит процесс

Автор: Lunatikus 11.9.2007, 08:33
SergeBS, строка вычислит сумму остатков.Плин,Я ,конечно,новичок в программировании БД и составлении запросов SQL.Но не считайте меня совсем дибилом.Значит я не так задачу расписал,что ты предлагаешь мне сумму.Хотите,чтобы я показал вам запрос,который дает календарь?ну ловите.Запрос на столь сложное вычисление значения следующей строки на основе вычисленного уже значения предыдущей.Уже я сделал тему в разделе MS SQL на эту тему,как запросом сделать подобное вычисление.А теперь посмотрите на запрос,который выдает календарь.Писать все таблицы и объяснять,как создавался запрос смысла не вижу-никто не захочет разбираться во множественных связях 5 таблиц и таком вот запросе:

Код

SELECT A.data,A.univer,A.ostatok,A.prognoz,A.kolc,B.razmer,A.zayavka,A.x FROM 
         (
         SELECT deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,A.kolc,deal_table.x 
         FROM (
                    (
                    SELECT deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,
                                  sum(v_puti_msk.kolc)*univer_msk.[Коэффициент пересчета] as kolc,deal_table.x                       
                        FROM deal_table,univer_msk,v_puti_msk 
                     WHERE deal_table.x=''new'' AND 
                                 deal_table.univer=univer_msk.универартикул AND 
                                 univer_msk.COD_ARTIC=v_puti_msk.art AND 
                                 deal_table.data=v_puti_msk.date AND 
                                 univer_msk.[Пред-во]=''Питер'' 
                GROUP BY deal_table.x,deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,univer_msk.[Коэффициент пересчета]
                     ) AS A 
                     RIGHT JOIN deal_table 
                     ON A.univer=deal_table.univer AND A.data=deal_table.data AND A.x=''new''
                   )
          ) AS A INNER JOIN 
         (
         SELECT deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,B.razmer,deal_table.x 
         FROM (
                    (
                     SELECT deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,sum(ZAK.razmer)*univer_msk.[Коэффициент пересчета] as razmer ,deal_table.x 
                     FROM deal_table,univer_msk,zak_msk 
                     WHERE deal_table.x=''new'' AND 
                                 deal_table.univer=univer_msk.универартикул AND 
                                 univer_msk.универартикул=zak.univer AND 
                                 deal_table.data=zak.data_zak AND 
                                 univer_msk.[Пред-во]=''Питер'' 
                GROUP BY deal_table.x,deal_table.data,deal_table.univer,deal_table.ostatok,deal_table.prognoz,deal_table.zayavka,univer_msk.[Коэффициент пересчета]
                    ) AS B 
                    RIGHT JOIN deal_table 
                    ON B.univer=deal_table.univer AND B.data=deal_table.data AND B.x=''new''
                  )
          ) AS B 
         ON A.data=B.data AND A.univer=B.univer AND A.x=''new'' AND B.x=''new'' 
         ORDER BY A.univer,A.data

никто не захочет тратить время на разборку этого,или я не прав?)

Добавлено через 1 минуту и 58 секунд
Akella, как можно перевести в хранимую процедуру выполнение кода проги?Мне для начала тогда надо запросом вычисления сделать.А если это получится и так все будет сервер выполнять...чет я запутался...

Автор: kobra 11.9.2007, 12:25
честно скозать, не понял алгоритм, но в принципе наверное это не стол важно.
лично я, в любом случае сделал бы на сервере.  хатя бы потому что гонять милион записеи по сети не етично.
но что косается 
Цитата(Lunatikus @  10.9.2007,  13:01 Найти цитируемый пост)
если бы из адоквери можно было вытащить значение не текущей и я бы это знал,я бы не парился со списком отдельным
если точно помню эта функция называется lookup

Автор: Lunatikus 11.9.2007, 12:43
а как долго будет выполняться запрос лукапа в каждом шаге цикла на миллион шагов ?)

Автор: Akella 11.9.2007, 13:11
Цитата(Lunatikus @  10.9.2007,  14:26 Найти цитируемый пост)
редставь себе хотя бы 10 полей типа врачар(255) в миллион строк...и все это вариант... 

это у тебя на клиенте молотится?
так пусть на сервере

Добавлено через 3 минуты и 8 секунд
просто у меня тоже стоит задача, если ты видел мой пост здесь, в БД, я начал молотить циклы на клиенте, ОООчень долго, но мне помогли это перевести на сервер (FB), процедура отрабатывает за 4-5 секунд

Автор: Lunatikus 11.9.2007, 13:34
у меня сервер MS SQL 2000.Как можно сделать процедуру,выполняемую сервером по вычислению полей?Без запроса ведь никак.Вот и думаю теперь как сделать запросом расчеты...а так все запросы у меня сервер выполняет,конечно

Автор: Akella 11.9.2007, 14:45
Цитата(Lunatikus @  11.9.2007,  13:34 Найти цитируемый пост)
Как можно сделать процедуру,выполняемую сервером по вычислению полей?Без запроса

а что MS SQL не позволяет делать выборки внутри хранимок?

Автор: Lunatikus 11.9.2007, 14:58
конечно позволяет.Мы не так друг друга поняли =) я говорю о цикле перебора записей while...do... разве такое можно сохранить в "хранимках"?

Автор: ALeXandrK 11.9.2007, 15:17
Цитата(SergeBS @ 11.9.2007,  07:46)
ALeXandrK, 
Цитата

Богат ни тот, у кого много, а тот, кому хватает

Не "ни тот", а "нЕ тот"!

А может я очень сильно отрицаю, тогда можно и НИ smile 

Автор: SergeBS 11.9.2007, 16:00
Lunatikus, 
Объясни все-таки понятнее, что вычисляешь. Именно для A1, например. Берешь на 02.01.2007 ostatok, из него вычитаешь на 01.01.2007 ostatok и т.д. до конца? Я ничего из этого не понял:
Цитата
ДЛя каждого артикула свой календарь,В котором ко дню привязан определенный остаток,прогноз(получается в минус остатка текущего),заказ(тоже в минус остатку),приход товара(в плюс).На основе этих полей надо просчитать остатки будущих дней(прогноз,заказы и приходы будущих дней известны и известен остаток на текущий день). ...

Что из чего вычитается и т.п.?

Автор: Lunatikus 11.9.2007, 16:04
вычитаю из первого ostatka (т.е. на 01.01.2007) значения полей zakaz,prognoz.Полученное значение записываю под датой 02.01.2007 запросом в таблицу.Смещаюсь на 02.01.2007 и уже из нового остатка(он сохранен в переменной) вычитаю prognoz,zakaz текущей строки.И так до самого конца.Когда наталкиваюсь на смену артикула,сбрасываю значение переменной и заменяю стоящим в текущей строке.,хранящей убывающий остаток.Понятно объясняю?

Автор: SergeBS 12.9.2007, 07:27
ALeXandrK, 
Цитата
А может я очень сильно отрицаю, тогда можно и НИ 

Нельзя. НИ - только при перечислении.

Lunatikus, 
Тогда BOL тебе в руки - CURSOR. Они как раз для таких построчных обработок сделаны. Или делай хранимку, которая будет высылать результат вычитания. БУдешь тогда смотреть только на дату и артикул - трафик сети резко упадет. И еще: если взять первый ostatok, из него вычесть суммы prognoz + zakaz для выбранного артикула, то по твоему описанию - получается сразу конечный результат. Или в описании что-то упущено. Например необходимость заполнения всех полей ostatok.

Автор: Lunatikus 12.9.2007, 08:06
да,необходимость эта есть,не только изза того,что надо вносить новые значения остатков в каждой строке,но и потому,что вычисления надо делать до тех пор,пока остаток не станет нулем или отрицательным.НАсчет хранимок-наверное,стоит разобраться,что же это такое и как работает,буду искать...

Автор: Akella 12.9.2007, 09:07
Цитата(Lunatikus @  11.9.2007,  14:58 Найти цитируемый пост)
я говорю о цикле перебора записей while...do... разве такое можно сохранить в "хранимках"?

сохранить в хранимке? зачем там сохранять? Хранимка пробежалась по набору данных (НД), выдала резальтат и всё и ничего хрнаить в ней не нужно, для этого есть таблицы.

Автор: ALeXandrK 12.9.2007, 13:18
Цитата(SergeBS @ 12.9.2007,  07:27)
ALeXandrK, 
Цитата
А может я очень сильно отрицаю, тогда можно и НИ 

Нельзя. НИ - только при перечислении.

 smile 
http://www.gramma.ru/RUS/?id=13.7. 
Есть там пунктик "ни для усиления отрицания" -  и написано там, что обычно оно применяется,
когда уже есть отрицание, а обычно не значит обязательно...
Я не говорю, что ты не прав, но вот НИ мне больше по-душе в этом случае smile 
... ну это отвлечения...

Lunatikus: Так может тебе создать запрос (в том же SQL, кот. будет тебе считать и
обновлять), а уже в цикле вызывать этот запрос с помощью TADOStoredProc.
Всяко будет быстрее, чем использовать Next, пробегая по всем полям.

Автор: kobra 12.9.2007, 16:35
Цитата(Lunatikus @  11.9.2007,  16:04 Найти цитируемый пост)
И так до самого конца.Когда наталкиваюсь на смену артикула,сбрасываю значение переменной и заменяю стоящим в текущей строке.,

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)