gifts2017

Прямой запрос к SQL-базе: количество дней наличия товара на складе за период

Опубликовал Алексей Бочков (Aleksey.Bochkov) в раздел Программирование - Практика программирования

tormozit в своей статье http://infostart.ru/articles/228/ приводил пример для "восьмерки", идея мне понравилась, поэтому решил из-за производственной необходимости переписать на прямой запрос к SQL-базе 7.7...
Чуть позже, если получится, перепишу для dbf-базы.
SELECT 
Подзапрос.ПодзапросНоменклатура [ПодзапросНоменклатура $Справочник.Номенклатура],
Подзапрос.ПодзапросСклад [ПодзапросСклад $Справочник.Склады],
SUM(
 CASE WHEN    Подзапрос.ПодзапросПериод  = $НачалоПериода.День(:ДатаКонца~)               THEN
   CASE WHEN Подзапрос.КоличествоКонечныйОстаток > 0 THEN
     CASE WHEN   Подзапрос. ПодзапросКоличествоКонечныйОстаток <= 0       THEN
        DATEDIFF(day, Подзапрос.ОстаткиТМЦОстаткиОбороты1Период,  Подзапрос.ПодзапросПериод)
     ELSE
        DATEDIFF(day, Подзапрос.ОстаткиТМЦОстаткиОбороты1Период,  :ДатаКонца~) + 1
     END
   ELSE
     CASE WHEN Подзапрос.ПодзапросКоличествоКонечныйОстаток > 0 THEN
        DATEDIFF(day, Подзапрос.ПодзапросПериод,  :ДатаКонца~) + 1
     ELSE 
        0 
     END
   END
 ELSE
   CASE WHEN Подзапрос.КоличествоКонечныйОстаток > 0 THEN
     DATEDIFF(day, Подзапрос.ОстаткиТМЦОстаткиОбороты1Период,  Подзапрос.ПодзапросПериод) 
   ELSE 
     0
   END
 END
) as КоличествоДнейВПродаже
FROM (
      SELECT Запрос2Уровня.ПодзапросНоменклатура ПодзапросНоменклатура
		, Запрос2Уровня.ПодзапросСклад ПодзапросСклад
		, Запрос2Уровня.ПодзапросКоличествоКонечныйОстаток
		, Запрос2Уровня.ПодзапросПериод
		, Запрос2Уровня.ОстаткиТМЦОстаткиОбороты1Период
		, Запрос2Уровня.КоличествоКонечныйОстаток
      FROM (
                SELECT Запрос1Уровня.Номенклатура ПодзапросНоменклатура
			, Запрос1Уровня.Склад ПодзапросСклад
			, Запрос1Уровня.КоличествоКонечныйОстаток ПодзапросКоличествоКонечныйОстаток
			, Запрос1Уровня.Период ПодзапросПериод
			, Запрос1Уровня.ОстаткиТМЦОстаткиОбороты1Период
			, ОстаткиТМЦОстаткиОбороты.КоличествоКонечныйОстаток
		FROM $РегистрОстаткиОбороты.ОстаткиТМЦ(:ДатаНачала,:ДатаКонца~,День,,,,(Номенклатура, Склад),) AS ОстаткиТМЦОстаткиОбороты
		INNER JOIN (
                        SELECT ОстаткиТМЦОстаткиОбороты.Номенклатура
				, ОстаткиТМЦОстаткиОбороты.Склад
				, ОстаткиТМЦОстаткиОбороты.КоличествоКонечныйОстаток
				, ОстаткиТМЦОстаткиОбороты.Период
				, MAX(ОстаткиТМЦОстаткиОбороты1.Период) ОстаткиТМЦОстаткиОбороты1Период
			FROM $РегистрОстаткиОбороты.ОстаткиТМЦ(:ДатаНачала,:ДатаКонца~,День,,,,(Номенклатура, Склад),) AS ОстаткиТМЦОстаткиОбороты
			LEFT JOIN $РегистрОстаткиОбороты.ОстаткиТМЦ(:ДатаНачала,:ДатаКонца~,День,,,,(Номенклатура, Склад),) AS ОстаткиТМЦОстаткиОбороты1 
			ON ОстаткиТМЦОстаткиОбороты.Номенклатура = ОстаткиТМЦОстаткиОбороты1.Номенклатура AND ОстаткиТМЦОстаткиОбороты.Склад = ОстаткиТМЦОстаткиОбороты1.Склад AND
			ОстаткиТМЦОстаткиОбороты.Период > ОстаткиТМЦОстаткиОбороты1.Период
			GROUP BY ОстаткиТМЦОстаткиОбороты.Номенклатура
				, ОстаткиТМЦОстаткиОбороты.Склад
				, ОстаткиТМЦОстаткиОбороты.КоличествоКонечныйОстаток
				, ОстаткиТМЦОстаткиОбороты.Период
                        ) AS Запрос1Уровня 
			ON ОстаткиТМЦОстаткиОбороты.Номенклатура = Запрос1Уровня.Номенклатура AND ОстаткиТМЦОстаткиОбороты.Склад = Запрос1Уровня.Склад AND 
			ОстаткиТМЦОстаткиОбороты.Период = Запрос1Уровня.ОстаткиТМЦОстаткиОбороты1Период
                ) AS Запрос2Уровня
      ) AS Подзапрос
GROUP BY Подзапрос.ПодзапросНоменклатура
	, Подзапрос.ПодзапросСклад
ORDER BY Подзапрос.ПодзапросНоменклатура
	, Подзапрос.ПодзапросСклад

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Георгий Уткин-Севастьянов (coloboc) 18.05.10 18:38
Крутил этот вариант по всякому... Не сказал бы, что он у меня не заработал. Но данные давал не все, хотябы только потому, что отсутствует параметр "ДвиженияИГраницыПериода". При этом ничего лучшего в интернете не нашел. После продолжительного обдумывания, родился вот такой вариант, намного более простой и быстрый. Надеюсь он комунибудь окажется полезен.
Приведённый запрос целиком выдернут из рабочей обработки, получает количество дней товара на складе за указанный период (ТиС, 7.7, SQL 2000)

	SELECT
	|	ВлЗапрос.Фирма [Фирма $Справочник.Фирмы] 
	|	,ВлЗапрос.Номенклатура [ПодзапросНоменклатура $Справочник.Номенклатура]
	|	,SUM(
	|	CASE WHEN ВлЗапрос.НачОст>0 THEN  
	|		CASE WHEN ВлЗапрос.Период=convert(datetime,:НачДата,112) THEN
	|                             		CASE WHEN ВлЗапрос.КонОст<=0 THEN   
	|				1
	|			ELSE
	|				DATEDIFF(day, ВлЗапрос.Период,convert(datetime,:КонДата,112)) + 1
	|			END 
	|		ELSE 
	|               		CASE WHEN ВлЗапрос.КонОст<=0 THEN
	|				-DATEDIFF(day, ВлЗапрос.Период,convert(datetime,:КонДата,112))
	|			END
	|		END                
	|	ELSE
	|		CASE WHEN ВлЗапрос.КонОст>0 THEN 
	|			DATEDIFF(day, ВлЗапрос.Период,convert(datetime,:КонДата,112)) + 1 
	|		END
	|	END) as ДнейНаСкладе
	|FROM(
	|	SELECT ОстаткиТМЦОстаткиОбороты.Фирма
	|		, ОстаткиТМЦОстаткиОбороты.Номенклатура       
	|		, ОстаткиТМЦОстаткиОбороты.Период as Период
	|		, ОстаткиТМЦОстаткиОбороты.КоличествоКонечныйОстаток КонОст
	|		, ОстаткиТМЦОстаткиОбороты.КоличествоНачальныйОстаток НачОст 
	|	FROM  $РегистрОстаткиОбороты.ОстаткиТМЦ(:НачДата,:КонДата~,День,ДвиженияИГраницыПериода,
	|					,
	|					Номенклатура in (select val from #СписокТоваров) 
	|					,(Номенклатура, Фирма),) AS ОстаткиТМЦОстаткиОбороты 
	|	) AS ВлЗапрос           
	|	GROUP BY ВлЗапрос.Фирма
	|		, ВлЗапрос.Номенклатура 
	|	ORDER BY ВлЗапрос.Номенклатура";
...Показать Скрыть
Dartvader; Bor_ka; +2 Ответить