Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Помогите с SQL-запросом (число прочтений - 3164 )
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Помогите с SQL-запросом
23. Мая 2008 :: 10:08
Печать  
Вот такой запрос:
Код
Выбрать все
select S.Article as ИДД,
 Sum(case S.outgo when 0 then 0-S.Quantity when 1 then S.Quantity end) as Количество, 0 as Приход
 from sales S (nolock) where Date>'20060201' and Date<'99990101' and Firm='10110840000000458'
 and division = 9 and Article not in
   (select Article from Sales (nolock) where Date<='20060201' and Date>='20060101'
 and Firm='10110840000000458' and division=9 and Outgo=1 group by Article)
  group by S.Article 

вроде ничего сложного, но отрабатывает за слишком долгое время:   Cumulative wait time on server replies   2,1514e+007      
Загрузка проца при этом под 100% Печаль
Индекс такой:
Код
Выбрать все
CREATE UNIQUE CLUSTERED
  INDEX [PK_Sales] ON [dbo].[Sales] ([Date], [Firm], [Division], [Article], [Property], [Supplier], [Status], [Type], [Outgo])
WITH
    DROP_EXISTING
ON [PRIMARY] 


На счет этого: Date<'99990101'  - данные только до 08.02.2006. Помогите соптимизировать запрос, пожалуйста.
  
Наверх
ICQ  
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #1 - 23. Мая 2008 :: 10:16
Печать  
Если выполнить селекты поотдельности, то результат такой:
1) Селект без последнего условия
Код
Выбрать все
select S.Article as ИДД,
 Sum(case S.outgo when 0 then 0-S.Quantity when 1 then S.Quantity end) as Количество, 0 as Приход
 from sales S (nolock) where Date>'20060201' and Date<'99990101' and Firm='10110840000000458'
 and division = 9 group by S.Article 

    Cumulative wait time on server replies 294      
2) Только последний селект
Код
Выбрать все
select Article from Sales (nolock) where Date<='20060201' and Date>='20060101'
 and Firm='10110840000000458' and division=9 and Outgo=1 group by Article 

    Cumulative wait time on server replies 300            
  
Наверх
ICQ  
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #2 - 23. Мая 2008 :: 10:24
Печать  
group by - накуя?
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #3 - 23. Мая 2008 :: 10:37
Печать  
Цитата:
group by - накуя?

Во втором запросе? Ну... выборка может получится и из большого количества записей, а так - типа объединяю. И потом - эти запросы, поотдельности выполняются доли секунды, видимо вместе - индекс не используется Печаль
  
Наверх
ICQ  
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #4 - 23. Мая 2008 :: 11:02
Печать  
А если поставить в индексе Date после Article?
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #5 - 23. Мая 2008 :: 11:28
Печать  
berezdetsky писал(а) 23. Мая 2008 :: 11:02:
А если поставить в индексе Date после Article?

Индекс не мой Печаль я лишь структурой пользуюсь
  
Наверх
ICQ  
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #6 - 23. Мая 2008 :: 11:29
Печать  
Переделал на два запроса Первым выборку кидаю во временную таблицу, вторым получаю окончательные данные - выполняется все это 13 сек, целый запрос - 76 сек.
  
Наверх
ICQ  
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #7 - 23. Мая 2008 :: 12:00
Печать  
Хых, сделал выборку select Article into #tm1 from Articles where Article not in (select Article from Sales (nolock) where Date<='20060201' and Date>='20060101'
and Firm='10110840000000458' and division=9 and Outgo=1 group by Article)
и
select S.Article as ИДД,
Sum(case S.outgo when 0 then 0-S.Quantity when 1 then S.Quantity end) as Количество, 0 as Приход
from sales S (nolock) where Date>'20060201' and Date<'99990101' and Firm='10110840000000458'
and division = 9 and Article in
   (select Article from #tm1) group by S.Article
Отработало за секунду
  
Наверх
ICQ  
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #8 - 23. Мая 2008 :: 12:44
Печать  
select distinct Article ... group by Article
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #9 - 23. Мая 2008 :: 15:35
Печать  
Цитата:
select distinct Article ... group by Article

Даже не вспомнил бы об этом, спасибо!
  
Наверх
ICQ  
IP записан
 
pvase
God Member
*****
Отсутствует



Сообщений: 923
Местоположение: Киев
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #10 - 26. Мая 2008 :: 17:19
Печать  
Примерно так:
Код
Выбрать все
select
	S.Article as ИДД,
	Sum(S.Quantity*S.outgo - S.Quantity*((S.outgo+1)%2)) as Количество,
	0 as Приход
from sales S (nolock)
where
	S.Date>'20060201'
	--and S.Date<'99990101'
	and S.Firm='10110840000000458'
	and S.division = 9
	and S.Article not in
   (select Article from Sales (nolock) where Date<='20060201' and Date>='20060101'
	and Firm='10110840000000458' and division=9 and Outgo=1
	--group by Article
	)
  group by S.Article  


Если убрать последний group by - нельзя не сработает агрегация.
  
Наверх
IP записан
 
Salimbek
God Member
*****
Отсутствует



Сообщений: 862
Зарегистрирован: 06. Июня 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #11 - 26. Мая 2008 :: 18:37
Печать  
Цитата:
Примерно так:

К сожалению так плохо работает, время отработки разных вариантов запроса я уже приводил. Дело в том, что при данном варианте (видимо) перестает использоваться индекс и SQL сваливается в Скан.
Теперь почему у меня есть эта строка: "and S.Date<'99990101'"  - дело в том, что когда я резал эту базу, типа delete from Sales where date<'Нужная дата' запрос отрабатывался оч-ч-чень долго, после анализа пришли к выводу, что SQL не мог определить - есть ли нужные данные только в выбранном диапазоне и сканировал все записи, после явного указания второй границы, пусть и в идиотских размерах (S.Date>'00010101') но запрос существенно ускорился, с тех пор, просто по привычке, пишу именно так.
Окончательный вариант запросов выглядит так:
Код
Выбрать все
	Состояние("Копируем остатки");
	ТекстЗапроса="select Article as ИДД, Sum(Quantity) as Количество, 0 as Приход into #tmp from remains (nolock)
	| where Date>='"+Дата2+"' and division="+КодМагазина+" and Firm='"+Фирма+"' and Article not in
	|   (select Article from Sales (nolock) where Date<='"+Дата2+"' and Date>='"+Дата1+"'
	| and Firm='"+Фирма+"' and division="+КодМагазина+" and Outgo=1) group by Article";
	РС.ВыполнитьСкалярный(ТекстЗапроса);
	// Добавляем в эту таблицу Движения За период с конечной даты отчета по текущую дату
	Состояние("Обновляем их новыми данными");
	ТекстЗапроса = "Update #tmp set Количество=Количество+S1.Bonus
	| from (Select Article, Sum(case outgo when 0 then 0-Quantity when 1 then Quantity end) as Bonus
	|	    from sales (nolock) where Date>'"+Дата2+"' and Date<'99990101' and division = "+КодМагазина+"
	|	    and Firm='"+Фирма+"' group by Article) S1
	| where #tmp.ИДД=S1.Article";
	РС.ВыполнитьСкалярный(ТекстЗапроса);

	Состояние("Создаем промежуточную таблицу");
	ТекстЗапроса = "select DISTINCT Article into #tm1 from Sales (nolock) where Date<='"+Дата2+"' and Date>='"+Дата1+"'
	| and Firm='"+Фирма+"' and division="+КодМагазина+" and Outgo=1 UNION select ИДД as Article from #tmp";
	РС.ВыполнитьСкалярный(ТекстЗапроса);

	ТекстЗапроса = "insert into #tmp select S.Article as ИДД,
	| Sum(case S.outgo when 0 then 0-S.Quantity when 1 then S.Quantity end) as Количество, 0 as Приход
	| from sales S (nolock) where Date>'"+Дата2+"' and Date<'99990101' and division = "+КодМагазина+"
	| and Firm='"+Фирма+"' and Article not in
	|   (select Article from #tm1 (nolock)) group by S.Article";
	Состояние("Добавляем полностью проданное");
	РС.ВыполнитьСкалярный(ТекстЗапроса);
	//Фиксируем поступление за рассматриваемый период
	ТекстЗапроса = "Update #tmp set Приход=Приход+S1.Bonus
	| from (select Article, Sum(Quantity) Bonus from Sales (nolock) where Date<='"+Дата2+"' and Date>='"+Дата1+"'
	| and division="+КодМагазина+" and Firm='"+Фирма+"' and Outgo=0 group by Article) S1
	| where #tmp.ИДД=S1.Article";
	Состояние("Фиксируем поступление за период");
	РС.ВыполнитьСкалярный(ТекстЗапроса);

	// Выводим содержимое этой таблицы, за исключением строк с нулевым остатком,
	// и строк, у которых остаток равен сумме прихода за рассматриваемый период
	// так как это значит, что на начало запроса этого товара не было
	ТекстЗапроса="select A.Name as Товар, A.Code as Код, R.ИДД as ИДД, R.Количество as Остаток
	| from #tmp R (nolock) left join Articles A (nolock) on A.Article=R.ИДД where R.Количество<>0 and
	| R.Количество<>(R.Приход)";
	Состояние("Получаем товары без движения");
	РС.ВыполнитьИнструкцию(ТекстЗапроса,ТЗ,1);
 


З.Ы. Все таки Астор, хоть и попа, но при грамотном использовании и он способен на чЮдеса Улыбка
  
Наверх
ICQ  
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #12 - 27. Мая 2008 :: 10:56
Печать  
Точняг
Про ограничение дат кто-то писал уже где-то
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
pvase
God Member
*****
Отсутствует



Сообщений: 923
Местоположение: Киев
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите с SQL-запросом
Ответ #13 - 28. Мая 2008 :: 06:12
Печать  
По идее одного упоминания даты достаточно чтобы задействовать индекс.
Проблема сокрее всего вот здесь:
"INDEX [PK_Sales] ON [dbo].[Sales] ([Date], [Firm], [Division], [Article], [Property], [Supplier], [Status], [Type], [Outgo])"

Соответсвенно чтобы индекс работал как следует надо указать все поля (очередность также желательно такую же, хотя может оптимизатор зарпосов и сам поймет последовательность). Т.е. в подзапросе надо было условие стаивить:
Код
Выбрать все
(select Article from Sales (nolock)
		where Date<='20060201' and Date>='20060101'
	and Firm='10110840000000458'
		and division=9
		and Property = S.Property
		and Supplier = S.Supplier
		and Status = S.Status
		and Type = S.Type
		and Outgo=1
	--group by Article
	)
 


Хотя это может повлиять на логику и результат запроса.
  
Наверх
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать