Форум: "Базы";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
ВнизТак чтобы побыстрей работало ... Найти похожие ветки
← →
Vikuksa (2002-07-08 11:44) [0]Please, help!!! Есть парочка вложенных запросов, пока выполняются можно помереть со скуки. Как сделать чтобы побыстрее работало?
← →
Johnmen (2002-07-08 11:54) [1]А где же сами запросы ???
← →
Val (2002-07-08 12:10) [2]>Vikuksa
наверное, пока выполняются, зашел сюда? :)
← →
-=Sergeante=- (2002-07-08 12:12) [3]> Vikuksa
Надо оптимизировать запрос :)
← →
Леша (2002-07-08 12:14) [4]Можно проидексировать таблицы.
← →
Vikuksa (2002-07-08 12:43) [5]ADOQuery1.Active := false;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add("SELECT T_Emitent.sng FROM T_Emitent left JOIN T_Emission ON ");
ADOQuery1.SQL.Add("T_Emitent.SN = T_Emission.SNE RIGHT OUTER JOIN T_SRVEmitent ON T_Emitent.SN = T_SRVEmitent.SNE ");
ADOQuery1.SQL.Add("WHERE (T_SRVEmitent.F1 = 1) AND (T_SRVEmitent.F9 = 1) GROUP BY T_Emitent.sng ");
ADOQuery1.SQL.Add("HAVING (MAX(T_Emission.DataReg) <= CONVERT(DATETIME,""1997 - 01 - 08 00 : 00 : 00 "", 102)) ");
ADOQuery1.Active := true;
while not ADOQuery1.Eof do
begin
txt1 := ADOQuery1.fieldbyname("sng").AsString;
ADOQuery2.Active := false;
ADOQuery2.SQL.Clear;
ADOQuery2.SQL.Add("SELECT T_Emitent.sng FROM T_Emitent RIGHT JOIN T_DocFace ON T_Emitent.SN = T_DocFace.SNE ");
ADOQuery2.SQL.Add("WHERE (T_Emitent.sng = "+txt1+")");
ADOQuery2.SQL.Add("GROUP BY T_Emitent.sng, T_DocFace.F1, T_DocFace.F2, ");
ADOQuery2.SQL.Add("T_DocFace.F3 HAVING (T_DocFace.F1 = 1) AND (T_DocFace.F3 = 4)AND(T_DocFace.F2 = "+IntToStr(pp)+")");
ADOQuery2.Active := true;
if not ADOQuery2.Eof then inc(ii);
ADOQuery1.Next;
end;
ВОТ ПРИМЕРЧИК! И ЧТО????????
← →
TSV (2002-07-08 12:52) [6]> Vikuksa (08.07.02 12:43)
Ты по-нормальному запрос написать можешь?
← →
samalex1 (2002-07-08 13:27) [7]Я что-то не понимаю, зачем функция CONVERT, может ее убрать?
Действительно, не стоит добавлять отдельно по-строчкам, можно все целиком. Или !!! используй параметрические запросы (:par заместо "+txt1+"), очень удобно, поверь, или хранимые процедуры в SQL, еще удобнее.
← →
Telly_F (2002-07-08 13:34) [8]В добавление к Samalex1:
Еще глянь, а индексы по полям из where есть? Если есть - то какие? Попробуй с ними поработать...
← →
jonik pegas (2002-07-08 13:35) [9]Надо развлекать пользователя чтобы не скучал
(Например ProgressBar-ом или сообщениями "Идет выполнение запроса
осталось 10% или 1 Мин" с перекидывающей папки Avi-шкой):-)
Второй запрос сделать параметрическим
← →
Vikuksa (2002-07-08 13:49) [10]А ПО-НОРМАЛЬНОМУ ЕТО КАК?
← →
Anatoly Podgoretsky (2002-07-08 13:49) [11]О да у тебя декартово произведение q1*q2
← →
Vikuksa (2002-07-08 13:51) [12]Anatoly, Ты с какого дуба рухнул?
КАКОЕ ЕЩЕ ПРОИЗВЕДЕНИЕ?
← →
Vikuksa (2002-07-08 14:02) [13]Anatoly, извини! Объясни дурехе где ты нашел произведение!
← →
Johnmen (2002-07-08 14:17) [14]Отвечу за Anatoly Podgoretsky © :
Каждой записи из Q1 ты сопоставляешь все записи из Q2.
А Q2 в данном случае должен быть совсем другим, ведь тебе надо фактически лишь знать, есть ли хоть одна запись в Q2. (см. COUNT(*))
← →
Delirium (2002-07-08 14:21) [15]Я думаю, стоит пользоваться переменными:
declare @d datetime set @d="19970801"
select T_Emitent.sng
from T_Emitent
left join T_Emission on T_Emitent.SN = T_Emission.SNE
right join T_SRVEmitent on T_Emitent.SN = T_SRVEmitent.SNE
where (T_SRVEmitent.F1 = 1) and (T_SRVEmitent.F9 = 1)
group by T_Emitent.sng
having max(T_Emission.DataReg) <= @D
В цикле:
declare @txt varchar(50) set @txt="song"
declare @pp int set @pp=1
select T_Emitent.sng
from T_Emitent
right join T_DocFace on T_Emitent.SN = T_DocFace.SNE
where (T_Emitent.sng = @txt)
and (T_DocFace.F1 = 1)
and (T_DocFace.F3 = 4)
and (T_DocFace.F2 = @pp)
← →
Vikuksa (2002-07-08 14:23) [16]Johmen-чик через COUNT не получается! Я в Q1 вытаскиваю записи и каждую из них проверяю на еще одно условие с помощью Q2!
← →
Vikuksa (2002-07-08 14:23) [17]Johnmen-чик через COUNT не получается! Я в Q1 вытаскиваю записи и каждую из них проверяю на еще одно условие с помощью Q2!
← →
Delirium (2002-07-08 14:27) [18]Хм, может в запросе цикла не получать выборку, а только считать кол-во строк ?
declare @txt varchar(50) set @txt="song"
declare @pp int set @pp=1
select Count(*) as CountSng
from T_Emitent
right join T_DocFace on T_Emitent.SN = T_DocFace.SNE
where (T_Emitent.sng = @txt)
and (T_DocFace.F1 = 1)
and (T_DocFace.F3 = 4)
and (T_DocFace.F2 = @pp)
← →
Johnmen (2002-07-08 14:29) [19]Я что то не уловил : приведен не полный текст цикла ?
Если полный, то COUNT() !
← →
Vikuksa (2002-07-08 14:32) [20]Я могу прогруппировать только "sng", как только я ввожу COUNT группировка улетучивается!
← →
Delirium (2002-07-08 14:40) [21]> Vikuksa
Чётко оборисуй задачу: структура таблиц и смысл полей, ожидаемый результат. Мне думается, что можно обойтись и без Delphi-йского цикла, но надо понимать проблему...
← →
Vikuksa (2002-07-08 14:53) [22]T_Emitent: в ней человек, его номер, ndb.
T_SRVEmitent: обязан платить или нет.
T_Emission: кол-во платежей, когда платил.
T_DocFace: за что платил.
Связи: T_Emitent с T_SRVEmitent(ndb=1), с T_Emission(ndb-любой), с T_DocFace(ndb=2);
т.е. в T_Emitent есть человек и с ndb = 1 и c ndb = 2, а может быть только с ndb = 1!
Мне нужны все кто обязан платить и среди них у кого была оплата!
← →
Anatoly Podgoretsky (2002-07-08 15:03) [23]Vikuksa (08.07.02 13:51)
Насчет декартового произведения тебе уже объяснили, если у тебя в первом запросе 1000 записей, и во втром по тысяце, то у тебя будет обработано 1 000 000 записей, быстро это не будет, надо что то менять в запросах, постараться что бы это был один запрос а не q1*q2
← →
Vikuksa (2002-07-08 15:11) [24]Нее-е у меня во втором запросе смотрится есть ли хотябы одна запись по етому человеку
← →
Delirium (2002-07-08 15:13) [25]> Vikuksa
Я опишу одну таблицу, как я понял (в основном по запросу), а ты проверь и опиши остальные - грамотно ...
T_Emitent (
sn int not null, -- Идентификатор
sng int not null, -- искомый идентификатор
ndb int not null ) -- некий определитель, типа: 1-должен, 2-оплатил
← →
Vikuksa (2002-07-08 15:15) [26]не, не так. Я НЕ МОГУ ОПИСАТЬ ГРАМОТНО! опыта маловато...
← →
Delirium (2002-07-08 15:21) [27]> Vikuksa
Возьми скрипты из Query Analyzer-а, не торопись, просто никто не сможет правильно решить задачу, если условия поставлены не чётко :)
← →
Vikuksa (2002-07-08 15:31) [28]SELECT T_Emitent.SNG FROM T_Emitent left JOIN T_Emission ON
T_Emitent.SN = T_Emission.SNE RIGHT OUTER JOIN T_SRVEmitent ON T_Emitent.SN = T_SRVEmitent.SNE
WHERE (T_SRVEmitent.F1 = 1) AND (T_SRVEmitent.F9 = 1) GROUP BY T_Emitent.sng
HAVING (MAX(T_Emission.DataReg) <= "1997 - 01 - 08 ")
Это первый запрос, он вытаскивает всех людей(без повторения) кто обязан платить.
SELECT T_Emitent.sng FROM T_Emitent RIGHT JOIN T_DocFace ON T_Emitent.SN = T_DocFace.SNE
WHERE (T_Emitent.sng = "+txt1+")
GROUP BY T_Emitent.sng, T_DocFace.F1, T_DocFace.F2,
T_DocFace.F3 HAVING (T_DocFace.F1 = 1) AND (T_DocFace.F3 = 4)AND(T_DocFace.F2 = 2001)
Этот запрос проверяет есть ли у людя из списка Q1 хотя бы одна оплата, если есть то увеличивает счетчик,если нет то переходим к => записи Q1.
Связь между запросами идет по № человека!
ОООО!
← →
Vikuksa (2002-07-08 16:21) [29]Спасибо Delirium, бросил бедную девушку...
← →
Delirium (2002-07-08 16:32) [30]Вот некая оптимизация (не вдаваясь в смысл), надеюсь ты умеешь пользоваться NextRecordSet
set nocount on -- Чтобы не было ошибок с MultiRecordSets
-- настоятельно рекомендую для увеличения быстродействия
-- пользоваться переменными, особенно для datetime
declare @D datetime set @D="19970108"
-- "Это первый запрос, он вытаскивает всех людей(без повторения)
-- кто обязан платить."
-- сначала результат во временную таблицу
SELECT T_Emitent.SNG
into #mens
FROM T_Emitent
left JOIN T_Emission ON T_Emitent.SN = T_Emission.SNE
RIGHT JOIN T_SRVEmitent ON T_Emitent.SN = T_SRVEmitent.SNE
WHERE (T_SRVEmitent.F1 = 1)
AND (T_SRVEmitent.F9 = 1)
GROUP BY T_Emitent.sng
HAVING MAX(T_Emission.DataReg) <= @D
--"Это первый запрос..."
SELECT SNG from #mens
-- "Этот запрос проверяет есть ли у людя из списка Q1..."
-- берём сразу всех из времмной таблицы, и не вижу
-- никакого смысла в группировке
SELECT T_Emitent.sng
FROM T_Emitent
RIGHT JOIN T_DocFace ON T_Emitent.SN = T_DocFace.SNE
WHERE (T_Emitent.sng in (SELECT SNG from #mens) )
AND (T_DocFace.F1 = 1)
AND (T_DocFace.F3 = 4)
AND (T_DocFace.F2 = 2001)
-- убиваю временную таблицу
drop table #mens
← →
Delirium (2002-07-08 16:36) [31]если хочешь избавиться от повторений - пиши
select distinct ...
← →
Vikuksa (2002-07-08 16:41) [32]можно поподробнее про "избавиться от повторений"?
← →
Delirium (2002-07-08 16:43) [33]запрос:
select myField from myTable
результат:
a
a
a
a
a
запрос:
select distinct myField from myTable
результат:
a
← →
Vikuksa (2002-07-08 16:46) [34]Спасибо тебе большоо-ое!!! никогода тебя не забуду!!!
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.01 c