![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск разрывов в цепи следования. [D6, IB6.x]
Kinda © (2003-09-30 22:31:00)
Есть две таблицы с данными о движении вагонов.
В одной операции внутри страны, в другой - за
ее пределами. Необходимо отыскать разрывы в цепи следования,
например вагон выехал с одной страны, но не заехал в другую и т.п.
Я решил написать две ХП в одной сливаю данные двух таблиц, а в другой оранизован цикл по первой и внутри этого цикла
мне приходится опять же делать select из первой ХП чтобы посмотреть дату следующей операции и увидеть есть ли разрыв.
В результате все очень сильно тормозит, на 200 000 записей.
Скажите как можно сделать по-другому, только очень не хочется делать специальную таблицу для слива данных.
Заранее спасибо.
kaif (2003-10-02 01:31:00) [1]
Нет, я не это имею в виду.
Разумеется, запросы, вложенные в циклы FOR будут выполняться столько раз, сколько по ним FOR чешет.
FOR SELECT ...
DO
BEGIN
FOR SELECT ...
DO
BEGIN
END
END
Я говорю о случае, когда
FOR SELECT * FROM XP1 ORDER BY...
DO
BEGIN
bи здесь никаких запросов, а только сравнения с переменными
END
а сама XP1 возвращает набор, получаемый с помощью невложенных SELECT-ов, который упорядочивается перед тем, как цикл
FOR SELECT * FROM XP1
по нему пройдется.
Kinda (2003-10-01 18:33:00) [2]
Например, есть ХП, делающая запрос. Есть вторая ХП, "стоящая над ней" и делающая из нее запрос "2-го уровня". Сервер в таких случаях кеширует набор, возвращаемый первой процедурой и "вложенного перезапроса" не возникает.
Ты хочешь сказать, что если в ХП2 я создам
FOR SELECT * FROM ХП1 DO BEGIN
И здесь буду писать
SELECT ... FROM ХП1 WHERE...
....
END
То "вложенного перезапроса" из ХП1(200тыс. зап.) не возникнет?
У меня сейчас практически такое же решение, но на машине
Athlon XP 2400+ c 256Mb RAM ХП2 работала в течение 0,5 часа
и результатов не вернула, пришлось делать Shutdown!
kaif (2003-10-01 18:26:00) [3]
На моем компьютере сервер обходит наборы в ХП со скоростью не хуже 100тыс строк/сек. Поэтому я ожидаю, что такая стратегия будет решать задачу за несколько секунд.
kaif (2003-10-01 18:24:00) [4]
Допустим, мы делаем что-то вроде:
/*Объединение всех операций в один набор*/
CREATE PROC1
RETURNS(NVAGON INTEGER, DATAOP DATE)
AS
BEGIN
FOR SELECT NVAGON, DATAOP
FROM T1 WHERE
OPERATION = 1
INTO :NVAGON, :DATAOP
DO SUSPEND;
FOR SELECT NVAGON, DATEVH
FROM T2
INTO :NVAGON, :DATAOP
DO SUSPEND;
FOR SELECT NVAGON, DATEVIH
FROM T2
INTO :NVAGON, :DATAOP
DO SUSPEND;
END
CREATE PROC2
....
AS
BEGIN
FOR SELECT NVAGON, DATAOP FROM PROCE1
ORDER BY NVAGON, DATAOP
INTO :NVAGON, :DATAOP
DO
/*какая-то обработка, ловящая "дырки"*/
END
Во второй процедуре запросы первой отработают 1 раз, затем сервер упорядочит набор по вагонам и датам и как-то задачу дальше можно будет решить. Разумеется, я не все нужные поля использовал, но это набросок...
kaif (2003-10-01 18:17:00) [5]
Часто вопросы скорости я решал путем многокаскадных запросов. Например, есть ХП, делающая запрос. Есть вторая ХП, "стоящая над ней" и делающая из нее запрос "2-го уровня". Сервер в таких случаях кеширует набор, возвращаемый первой процедурой и "вложенного перезапроса" не возникает.
Можно вместо временной таблицы соорудить при помощи ХП имитирующий эту таблицу набор (сколь угодно сложно), а затем над ним произвести вторую выборку с помощью SELECT. Это работает быстрее, чем вставка 200тыс записей в таблицу TMP.
Я в задачу не вникал, но это как вариант стратегии поиска технического решения.
Kinda (2003-10-01 15:34:00) [6]
>Johnmen © (01.10.03 15:10) [18]
Я не совсем понял как это мы так получим?
Ведь в табл.2 нет поля OPERATION, к тому же
за пределами страны анализироваться должны
DATAVH и DATAVIH между странами.
Я хочу сказать, что DATAVIH-DATAVH по одной стране (KSTRAN)
запросто может быть (а оно так и есть) более 1 суток. Поэтому проанализировать надо DATAVIH,KSTRAN1 и DATAVH,KSTRAN2. И так
до возвращения на Родину.
Ух, блин, кажися придется все-таки сливать все это в какую-то временную таблицу :(
Johnmen (2003-10-01 15:10:00) [7]
Модифицировав запрос Sandman25 © (01.10.03 13:09), получаем вагоны, для которых есть разрыв при покидании Отчизны :)
SELECT DISTINCT T1.NVAGON
FROM Table1 T1
WHERE NOT EXISTS
(SELECT *
FROM Table2 T2
WHERE (T1.NVAGON=T2.NVAGON) AND
(T2.OPERATION=1) AND
(T2.DATEVH-T1.DATAOP<=1))
А для получения более развернутой информации надо написать ХП, в которой делается последовательный обход записей запроса
SELECT * FROM Table1 T1
JOIN Table2 ON T1.NVAGON=T2.NVAGON
ORDER BY <вагоны, даты и т.д.>
с анализом и принятием решения для каждой на основании каких-либо уже полученных значений, в рамках алгоритма...
Kinda (2003-10-01 13:56:00) [8]
>Sandman25 © (01.10.03 13:42) [16]
Потому что, как можно select"om объединить данные из двух
таблиц, причем с трансформацией структуры одной из них?
Sandman25 (2003-10-01 13:42:00) [9]
[15] Kinda © (01.10.03 13:37)
Тем более. Зачем вызывать одну хранимую для каждого вагона, если она каждый раз находит данные по всем вагонам?
Kinda (2003-10-01 13:37:00) [10]
>Sandman25 © (01.10.03 13:23) [13]
Данные возвращаемые процедурой надо сортировать!
GROUP BY NVAGON,DATAOP,OPERATION
Kinda (2003-10-01 13:27:00) [11]
> Johnmen © (01.10.03 13:20) [12]
Но ведь есть последовательность дат операций с вагоном!
Sandman25 (2003-10-01 13:23:00) [12]
Возможно, вместо вызова хранимой изнутри другой лучше написать прямой select.
Johnmen (2003-10-01 13:20:00) [13]
>Kinda © (01.10.03 13:11)
Теперь вроде бы понял окончательно...:)
Делаю вывод - НЕВОЗМОЖНО однозначноопределить желаемое, т.к. нет № рейса, о чем ты уже упомянул, или к.-л. сущность ему аналогичная. Ведь один и тот же вагон может много раз пересекать границу...
Kinda (2003-10-01 13:11:00) [14]
> Johnmen © (01.10.03 12:21) [9]
Алгоритм действительно запутанный.
Таблицы к сожалению проектированы не мной, т.е
я в таком виде получаю данные из внешнего мира.
Таблица 1 данные обновляется каждый день,
таблица 2 - каждый месяц.
Данные таблицы 1 используются не только для этой задачи,
поэтому операций с вагонами там больше, и как следствие
возникает избыточность данных (в контексте этой задачи).
> "Либо НЕВОЗМОЖНО однозначно определить разрыв,"
Что касается этого, то согласен с тем, что хорошо бы выделить рейс вагона (от момента погрузки до момента выгрузки, либо возвращения на территорию страны), но к сожалению такой возможности я не вижу.
Поэтому нужно привязаться к датам и операциям.
>И этот алгоритм ты так и не объяснил. На пальцах.
Алоритм таков:
1.Вагон вышел за пределы страны (Табл.1. OPERATION=1)
2.Далее в Табл.2 ДОЛЖНА (вот эти разрывы и надо найти если они есть) быть запись о входе этого вагона
на территорию другой страны(DATAVH=DATAOP хотябы в пределах суток).
3.Потом в той же записи Табл. 2 есть дата выхода с этой страны (DATAVIH) и нужно найти следующую запись в табл.2
(вход в следующую страну DATAVIH,KSTRAN1=DATAVH,KSTRAN2 и т.д.)
или в табл.1 (если он вернулся OPERATION=6)
Вот такой вот алгоритм.
Я не говорю, что все уже спроектировано, я прошу помочь мне это сделать чтобы устроить такую проверку.
Есть и еще кое-какие нюансы, сейчас их не привел, чтоб не запутаться.
Sandman25 (2003-10-01 13:09:00) [15]
ИМХО, лучше была бы структура такая:
table2
vagon - id вагона
nomer - номер операции (связка vagon, nomer уникальна)
date1 - дата операции
country - страна
type_operation - флаг (например 0 - вход в страну, 1 - выход из страны).
Тогда было бы легко найти разрыв с помощью
select distinct vagon
from vagons
where exists
(select *
from table2 a,
table2 b
where a.vagon = vagons.vagon
and b.vagon = a.vagon
and b.nomer = a.nomer + 1
and b.date1 >= a.date1 + 1)
А с текущей структурой придется во вложенном select вместо b.nomer = a.nomer + 1 писать конструкцию для нахождения следующей операции.
Johnmen (2003-10-01 12:21:00) [16]
>Anatoly Podgoretsky © (01.10.03 07:46)
Да, удалился вчера :0) Мама прогнала в кровать...
>Kinda ©
Я тут на досуге попытался осмыслить задачу...
Осмыслил. Вывод - неверно спроектированы таблицы, т.к. :
Либо НЕВОЗМОЖНО однозначно определить разрыв,
либо необоснованная избыточность данных, что приводит к запутанному алгоритму определения разрывов.
И этот алгоритм ты так и не объяснил. На пальцах.
Anatoly Podgoretsky (2003-10-01 07:46:00) [17]
Johnmen © (01.10.03 00:07) [5]
А ты еще не удалился :-)
Kinda (2003-10-01 00:47:00) [18]
Извиняюсь, но должен удалиться.
Очень буду благодарен за дельный совет.
Kinda (2003-10-01 00:28:00) [19]
В таблице 1:
OPERATION=1 - момент выхода за пределы страны
OPERATION=6 - момент возвращения
По сути таблица 2 содержит в каждой записи 2 операции с вагоном,
а именно вход в страну и выход из нее.
Вот еще поясню если вагон вышел за пределы страны, то он может проследовать N стран до своего возвращения вот эту цепь нужно и проследить, чтоб она не разрывалась. Т.е.:
Момент выхода -страна1 вход-страна1 выход-.....-момент возвращения.
Конечно немного закучено, но по-другому не получается.
Johnmen (2003-10-01 00:07:00) [20]
Давай дальше уточнять, а то нет однозначной ясности...
>Если с момента выхода вагона за пределы страны (табл. 1)
Где в табл.1 этот момент ? О какой стране речь - нашей/не нашей ?
>и до момента его возвращения
Где этот момент в табл. ?
Где производятся операции ? У нас или за бугром ? :)