Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вопрос по циклам  [new]
ferzmikk
Member

Откуда:
Сообщений: 2043
Здравствуйте!

+ Есть таблица
Юр лицо КодТТ SKU Дата начала Дата окончания Дата Отгрузки Продажи
00111 00001 SKU1 01.01.2018 10.01.2018 01.01.2018 5 4
00111 00001 SKU1 01.01.2018 10.01.2018 02.01.2018 0 1
00111 00001 SKU1 01.01.2018 10.01.2018 03.01.2018 0 0
00111 00001 SKU1 01.01.2018 10.01.2018 04.01.2018 5 2
00111 00001 SKU2 01.01.2018 10.01.2018 01.01.2018 0 3
00111 00001 SKU2 01.01.2018 10.01.2018 02.01.2018 0 0
00111 00001 SKU2 01.01.2018 10.01.2018 03.01.2018 0 0
00111 00001 SKU2 01.01.2018 10.01.2018 04.01.2018 3 1

+ Нужно получить такую таблицу
Юр лицо КодТТ SKU Дата начала Дата окончания Дата Отгрузки ПродажиПродажиОбраб
00111 00001 SKU1 01.01.2018 10.01.2018 01.01.2018 5 44
00111 00001 SKU1 01.01.2018 10.01.2018 02.01.2018 0 11
00111 00001 SKU1 01.01.2018 10.01.2018 03.01.2018 0 00
00111 00001 SKU1 01.01.2018 10.01.2018 04.01.2018 5 22
00111 00001 SKU2 01.01.2018 10.01.2018 01.01.2018 0 30
00111 00001 SKU2 01.01.2018 10.01.2018 02.01.2018 0 00
00111 00001 SKU2 01.01.2018 10.01.2018 03.01.2018 0 00
00111 00001 SKU2 01.01.2018 10.01.2018 04.01.2018 3 11

Логика заключается в том, чтобы по каждому Юр лицу + ТТ + SKU поле ПродажиОбраб равен полю Продажи, но учитывает с того дня, где присутствует первая отгрузка.

Тут получается надо пробегаться по циклам, то есть по датам по соответствующим Юр лицу + ТТ + SKU.

1. Скажите, для данной задачи каким образом можно пробежаться по циклам?
2. Если я правильно понимаю, если использовать WHILE, то добавляем только строки в таблицу, но не пробегаем по строкам. Верно?

+ SQL-запрос. Исходные данные
DECLARE @Таблица1 table
([Юр лицо] varchar (5),
	[КодТТ] varchar (8),
	[SKU] varchar (4),	
	[Дата начала] date,
	[Дата окончания] date,
	[Дата] date,	
	[Отгрузки] integer,
	[Продажи] integer
	)
;
INSERT INTO
  @Таблица1
VALUES 
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','01.01.2018',5,4),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','02.01.2018',0,1),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','03.01.2018',0,0),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','04.01.2018',5,2),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','01.01.2018',0,3),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','02.01.2018',0,0),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','03.01.2018',0,0),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','04.01.2018',3,1)
 ; 
23 янв 18, 11:32    [21129630]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
Добрый Э - Эх
Guest
ferzmikk,

циклы не нужны. всё и так сделать можно.
23 янв 18, 11:47    [21129720]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
tashkafox
Member

Откуда: Москва
Сообщений: 106
ferzmikk,
Посмотрите про оконные функции
23 янв 18, 11:53    [21129782]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
ferzmikk
Member

Откуда:
Сообщений: 2043
Установлена Microsoft SQL Server Management 2008.

SUM(Т1.[Отгрузки]) OVER (PARTITION BY Т1.[Юр лицо], Т1.[КодТТ], Т1.[SKU] ORDER BY Т1.[Дата] RANGE UNBOUNDED PRECEDING)
или
SUM(Т1.[Отгрузки]) OVER (PARTITION BY Т1.[Юр лицо], Т1.[КодТТ], Т1.[SKU] ORDER BY Т1.[Дата] ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
такие записи в этой версии не будут работать.

+ Если писать без этих оконных функции
DECLARE @Таблица1 table
([Юр лицо] varchar (5),
	[КодТТ] varchar (8),
	[SKU] varchar (4),	
	[Дата начала] date,
	[Дата окончания] date,
	[Дата] date,	
	[Отгрузки] integer,
	[Продажи] integer
	)
;
INSERT INTO
  @Таблица1
VALUES 
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','01.01.2018',5,4),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','02.01.2018',0,1),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','03.01.2018',0,0),
  ( '00111', '00001','SKU1','01.01.2018','04.01.2018','04.01.2018',5,2),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','01.01.2018',0,3),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','02.01.2018',0,0),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','03.01.2018',0,0),
  ( '00111', '00001','SKU2','01.01.2018','04.01.2018','04.01.2018',3,1)
 ; 

SELECT
	ТТ1.[Юр лицо],		
	ТТ1.[КодТТ],
	ТТ1.[SKU],
	ТТ1.[Дата начала],
	ТТ1.[Дата окончания],
	ТТ1.[Дата],
	ТТ1.[Отгрузки],
	ТТ1.[Продажи],
	CASE WHEN ТТ1. [Накопленные отгрузки] > 0 THEN ТТ1.[Продажи] ELSE 0 END AS [ПродажиОбраб]
FROM
	(SELECT
		Т1.[Юр лицо],		
		Т1.[КодТТ],
		Т1.[SKU],
		Т1.[Дата начала],
		Т1.[Дата окончания],
		Т1.[Дата],
		Т1.[Отгрузки],
		Т1.[Продажи],
		(SELECT
			SUM (Тв1.[Отгрузки])
		FROM
			@Таблица1 Тв1
		WHERE
			Т1.[Юр лицо] = Тв1.[Юр лицо]
			AND
			Т1.КодТТ = Тв1.КодТТ
			AND
			Т1.SKU = Тв1.SKU
			AND
			Т1.Дата >= Тв1.Дата) AS [Накопленные отгрузки]	
	FROM
		@Таблица1 Т1) AS ТТ1
Но для большой выборки такой способ подтормаживает
24 янв 18, 08:17    [21132665]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
aleks222
Guest
ferzmikk
Но для большой выборки такой способ подтормаживает

А чудесной кнопки нетути.

1. Индексы.
2. Расчет и сохранение в таблице. Обновление таблицы по мере необходимости.
3. Материализация через индексированные View.

ЗЫ. Ты ниповеришь, оконные функции "как-то так и считают". Так что, производительность на оконных не сильно превосходит "по старинке".
24 янв 18, 08:30    [21132687]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
ferzmikk
Member

Откуда:
Сообщений: 2043
ferzmikk
Логика заключается в том, чтобы по каждому Юр лицу + ТТ + SKU поле ПродажиОбраб равен полю Продажи, но учитывает с того дня, где присутствует первая отгрузка.

Это первый пункт условия. Есть еще и другие условия пунктов, где нужно пробегаться по дням, потом в случае необходимости возвращаются к предыдущим датам, но не с первого. Несколько циклов. Несколько переменных. Условия бывают меняются. И получится, что запрос будет сложно корректировать.

И вот хотел узнать, возможно ли сделать так: по каждому Юр лицу + ТТ + SKU в пользовательскую функцию передается массив или таблица из трех полей Дата, Отгрузки,Продажи (Оранжевый цвет) и возвращает массив по соответствующим строкам (голубой цвет). Аналогично для последующих Юр лицу + ТТ + SKU. Пользовательская функция была бы написана на VB.Net или C#. Возможно ли так? Если да то, как?

Юр лицо КодТТ SKU Дата начала Дата окончания Дата Отгрузки ПродажиПродажиОбраб
00111 00001 SKU1 01.01.2018 10.01.2018 01.01.2018 5 44
00111 00001 SKU1 01.01.2018 10.01.2018 02.01.2018 0 11
00111 00001 SKU1 01.01.2018 10.01.2018 03.01.2018 0 00
00111 00001 SKU1 01.01.2018 10.01.2018 04.01.2018 5 22
00111 00001 SKU2 01.01.2018 10.01.2018 01.01.2018 0 30
24 янв 18, 09:16    [21132793]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
ferzmikk
Member

Откуда:
Сообщений: 2043
ferzmikk
Юр лицо КодТТ SKU Дата начала Дата окончания Дата Отгрузки ПродажиПродажиОбраб
00111 00001 SKU1 01.01.2018 10.01.2018 01.01.2018 5 44
00111 00001 SKU1 01.01.2018 10.01.2018 02.01.2018 0 11
00111 00001 SKU1 01.01.2018 10.01.2018 03.01.2018 0 00
00111 00001 SKU1 01.01.2018 10.01.2018 04.01.2018 5 22
00111 00001 SKU2 01.01.2018 10.01.2018 01.01.2018 0 30
Так правильнее
Юр лицо КодТТ SKU Дата начала Дата окончания Дата Отгрузки ПродажиПродажиОбраб
00111 00001 SKU1 01.01.2018 10.01.2018 01.01.2018 5 44
00111 00001 SKU1 01.01.2018 10.01.2018 02.01.2018 0 11
00111 00001 SKU1 01.01.2018 10.01.2018 03.01.2018 0 00
00111 00001 SKU1 01.01.2018 10.01.2018 04.01.2018 5 22
24 янв 18, 10:31    [21133176]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7663
ferzmikk,

Вы должны пронумеровать отгрузки и сравнивать нарастающий итог продаж с отгрузкой. Как только продаж планируется абсолютно больше, чем отгрузок, прекращать продажи по текущему номеру продаж. Не нужны никакие циклы и переменные.
24 янв 18, 12:41    [21133988]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по циклам  [new]
ferzmikk
Member

Откуда:
Сообщений: 2043
Владислав Колосов
ferzmikk,

Вы должны пронумеровать отгрузки и сравнивать нарастающий итог продаж с отгрузкой. Как только продаж планируется абсолютно больше, чем отгрузок, прекращать продажи по текущему номеру продаж. Не нужны никакие циклы и переменные.

Я говорю, что есть и другие пункты условия. До этого реализовывал в экселе с помощью VBA. Код был не простым, но подтормаживал.
24 янв 18, 12:58    [21134084]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить