powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сравнение строк по заданным условиям
14 сообщений из 14, страница 1 из 1
Сравнение строк по заданным условиям
    #39619304
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!

Есть такая таблица.
Исходная таблицаКлиент Код ТТ SKU Дата Отгрузки шт Возвраты шт Реализация шт ЦенаКлиент1 ТТ1 SKU1 01.01.2014 1 0 1 100.00Клиент1 ТТ1 SKU1 03.01.2014 0 1 -1 100.00Клиент1 ТТ1 SKU1 05.01.2014 6 2 4 100.00Клиент1 ТТ1 SKU1 07.01.2014 5 1 4 150.00Клиент1 ТТ1 SKU1 09.01.2014 2 1 1 150.00Клиент1 ТТ1 SKU1 11.01.2014 1 0 1 100.00Клиент1 ТТ1 SKU2 01.01.2014 3 1 2 100.00Клиент1 ТТ1 SKU2 03.01.2014 2 0 2 50.00Клиент1 ТТ1 SKU2 05.01.2014 3 1 2 100.00Клиент1 ТТ1 SKU2 17.01.2014 2 0 2 100.00Клиент1 ТТ2 SKU1 01.01.2014 3 1 2 100.00Клиент1 ТТ2 SKU1 03.01.2014 1 0 1 100.00

Задача такая , что нужно отметить те строки-дни, где было ценовое мероприятие.

Для решения данной задачи ориентировался по цене. Сравнивал текущую строку и предыдущую с помощью оконной функции LAG. Если в предыдущей строке другая ТТ+SKU, то не сравнивает. Написал такой SQL-запрос, но он не законченный и работает не так как надо.
SQL-Запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
Declare @ДельтаПредел decimal(5,2) = 0.15

DECLARE @Таблица table(
	[Клиент] varchar(20),
	[Код ТТ] varchar(8),	
	[SKU] varchar(8),
	[Дата] date,
	[Отгрузки шт] numeric(8,0),
	[Возвраты шт] numeric(8,0),
	[Реализация шт] numeric(8,0),
	[Реализация сумма без НДС] numeric(8,0),
	[Цена] decimal(5,2))
;

INSERT INTO
  @Таблица
VALUES 
('Клиент1','ТТ1', 'SKU1', '01.01.2014', 1,0,1,100,100),
('Клиент1','ТТ1', 'SKU1', '03.01.2014', 0,1,-1,-100,100),
('Клиент1','ТТ1', 'SKU1', '05.01.2014', 6,2,4,400,100),
('Клиент1','ТТ1', 'SKU1', '07.01.2014', 5,1,4,600,150),
('Клиент1','ТТ1', 'SKU1', '09.01.2014', 2,1,1,150,150),
('Клиент1','ТТ1', 'SKU1', '11.01.2014', 1,0,1,100,100),
('Клиент1','ТТ1', 'SKU2', '01.01.2014', 3,1,2,200,100),
('Клиент1','ТТ1', 'SKU2', '03.01.2014', 2,0,2,100,50),
('Клиент1','ТТ1', 'SKU2', '05.01.2014', 3,1,2,200,100),
('Клиент1','ТТ1', 'SKU2', '17.01.2014', 2,0,2,200,100),
('Клиент1','ТТ2', 'SKU1', '01.01.2014', 3,1,2,200,100),
('Клиент1','ТТ2', 'SKU1', '03.01.2014', 1,0,1,100,100)
;

WITH
Таблица1 AS (
	SELECT
		[Клиент],
		[Код ТТ],	
		[SKU],
		[Дата],
		[Отгрузки шт],
		[Возвраты шт],
		[Реализация шт],
		[Реализация сумма без НДС],
		[Цена],
		IIF([Реализация шт] <>0,[Реализация сумма без НДС]/[Реализация шт] , Null) [Проверка],
		LAG([Код ТТ]) OVER(ORDER BY [Код ТТ]) [Код ТТ пред],
		LAG([SKU]) OVER(ORDER BY [SKU]) [SKU пред],
		LAG([Цена]) OVER(ORDER BY [Клиент],[Код ТТ],[SKU], [Дата]) [Цена пред]
	FROM
		@Таблица
),
Таблица2 AS (
	SELECT
		[Клиент],
		[Код ТТ],	
		[SKU],
		[Дата],
		[Отгрузки шт],
		[Возвраты шт],
		[Реализация шт],
		[Реализация сумма без НДС],
		[Цена],
		[Проверка],
		[Код ТТ пред],
		[SKU пред],
		[Цена пред],
		(CASE WHEN [Код ТТ] = [Код ТТ пред] AND [SKU] = [SKU пред] THEN 1 ELSE 0 END) [Предыдущее соответствие],
		(CASE
			WHEN [Код ТТ] = [Код ТТ пред] AND [SKU] = [SKU пред] THEN
				(CASE
                                        --Если цена одинаковая, но не мероприятие
					WHEN [Цена] = [Цена пред] THEN
						NUll
                                        --Если цена одинаковая, но мероприятие
					WHEN [Цена] = [Цена пред] THEN
						NUll
                                        --Если цена отличается
					ELSE
						(CASE
							WHEN [Цена] >= [Цена пред] THEN
								([Цена] - [Цена пред] )  /  [Цена пред]
							ELSE
								([Цена пред] - [Цена]) / [Цена]
						END)
				END)
			ELSE
			NULL
		END)
			[Дельта]
FROM
	Таблица1
),
Таблица3 AS (
	SELECT
		[Клиент],
		[Код ТТ],	
		[SKU],
		CONVERT(nvarchar(10), [Дата] , 104) AS [Дата],
		[Отгрузки шт],
		[Возвраты шт],
		[Реализация шт],	
		[Цена],	
		CAST([Дельта]AS decimal(10,2)) AS [Дельта],		
		IIF([Дельта] > @ДельтаПредел,1,0) [Мероприятие]
	FROM
		Таблица2
)
		
SELECT * FROM Таблица3


В общем, выдает такой результат
Результирующая таблицаКлиент Код ТТ SKU Дата Отгрузки шт Возвраты шт Реализация шт Цена Дельта МероприятиеКлиент1 ТТ1 SKU1 01.01.2014 1 0 1 100.00 NULL 0Клиент1 ТТ1 SKU1 03.01.2014 0 1 -1 100.00 NULL 0Клиент1 ТТ1 SKU1 05.01.2014 6 2 4 100.00 NULL 0Клиент1 ТТ1 SKU1 07.01.2014 5 1 4 150.00 0.50 1Клиент1 ТТ1 SKU1 09.01.2014 2 1 1 150.00 NULL 0Клиент1 ТТ1 SKU1 11.01.2014 1 0 1 100.00 0.50 1Клиент1 ТТ1 SKU2 01.01.2014 3 1 2 100.00 NULL 0Клиент1 ТТ1 SKU2 03.01.2014 2 0 2 50.00 1.00 1Клиент1 ТТ1 SKU2 05.01.2014 3 1 2 100.00 1.00 1Клиент1 ТТ1 SKU2 17.01.2014 2 0 2 100.00 NULL 0Клиент1 ТТ2 SKU1 01.01.2014 3 1 2 100.00 NULL 0Клиент1 ТТ2 SKU1 03.01.2014 1 0 1 100.00 NULL 0

Должно быть такКлиент Код ТТ SKU Дата Отгрузки шт Возвраты шт Реализация шт Цена Дельта МероприятиеКлиент1 ТТ1 SKU1 01.01.2014 1 0 1 100.00 NULL 0Клиент1 ТТ1 SKU1 03.01.2014 0 1 -1 100.00 NULL 0Клиент1 ТТ1 SKU1 05.01.2014 6 2 4 100.00 NULL 0Клиент1 ТТ1 SKU1 07.01.2014 5 1 4 150.00 0.50 1Клиент1 ТТ1 SKU1 09.01.2014 2 1 1 150.00 NULL 1 Клиент1 ТТ1 SKU1 11.01.2014 1 0 1 100.00 0.50 0 Клиент1 ТТ1 SKU2 01.01.2014 3 1 2 100.00 NULL 0Клиент1 ТТ1 SKU2 03.01.2014 2 0 2 50.00 1.00 1Клиент1 ТТ1 SKU2 05.01.2014 3 1 2 100.00 1.00 0 Клиент1 ТТ1 SKU2 17.01.2014 2 0 2 100.00 NULL 0Клиент1 ТТ2 SKU1 01.01.2014 3 1 2 100.00 NULL 0Клиент1 ТТ2 SKU1 03.01.2014 1 0 1 100.00 NULL 0

Проблема в том , то если мероприятие проводится второй день подряд, то отмечает что мероприятия нету. А также на следующий день мероприятие закончилось, но отмечает что присутствует мероприятие. Кажется тут надо смотреть не только предыдущие строки, но и предпредыдущие строки. Или смотреть на поле вычисляемое поле Мероприятие , где как раз смотрит значение на предыдущей строке этого же поля. Запутался в решении.

Следует учесть, что здесь отсутствуют строки-даты с нулевыми мерами. Не обращайте внимание на русскоязычные поля.

Как правильно написать SQL-запрос для решения данной задачи?
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619314
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkЕсли в предыдущей строке другая ТТ+SKU, то не сравнивает.А ORDER BY за тебя кто задавать будет?
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619369
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaferzmikkЕсли в предыдущей строке другая ТТ+SKU, то не сравнивает.А ORDER BY за тебя кто задавать будет?А строки отсортированы и поэтому не использую ORDER BY. Или в любом случае надо использовать?
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619375
waszkiewicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,
это кто тебе сказал, что строки отсортированы?
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619376
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
waszkiewiczferzmikk,
это кто тебе сказал, что строки отсортированы?
Таблица получается отдельной выгрузкой с помощью MDX-запроса. А MDX-запрос сортирует
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619384
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

Во-первых, чтобы определить предыдущую цену надо писать так:
Код: sql
1.
LAG([Цена]) OVER(Partition by [Клиент],[Код ТТ],[SKU] ORDER BY  [Дата]) [Цена пред]



Во-вторых, исходя из желаемого результата тебя интересуют изменения цены относительно "базовой", но как определить эту базовую цену?
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619385
waszkiewicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkwaszkiewiczferzmikk,
это кто тебе сказал, что строки отсортированы?
Таблица получается отдельной выгрузкой с помощью MDX-запроса. А MDX-запрос сортирует
серверу это расскажешь
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619447
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kopellyferzmikk,

Во-первых, чтобы определить предыдущую цену надо писать так:
Код: sql
1.
LAG([Цена]) OVER(Partition by [Клиент],[Код ТТ],[SKU] ORDER BY  [Дата]) [Цена пред]


Тогда для полей [Код ТТ пред] и [SKU пред] получается тоже надо писать так
Код: sql
1.
2.
LAG([Код ТТ]) OVER(Partition by [Клиент] ORDER BY [Код ТТ]) [Код ТТ пред],
LAG([SKU]) OVER(Partition by [Клиент],[Код ТТ] ORDER BY [SKU]) [SKU пред],


Верно или оставить как было?
Во-вторых, исходя из желаемого результата тебя интересуют изменения цены относительно "базовой", но как определить эту базовую цену?
Если Вы имеете ввиду для первой строки, то значение не известно. Пока решение вижу такое, что для 1 и 2 числа января каждого года это мероприятие и цена одинаковая, следовательно, в эти дни проходит мероприятие. И если на какой то день цена изменится, то это будет базовая цена. Может по такой логике определять базовую цену? Или как то определить базовую цену за первые 30 дней. Предполагается, что в одном мероприятии одна цена.

Если Вы имеете ввиду строку до мероприятия и последующие строки с мероприятием, то думаю будет нужна переменная, которая хранит базовую цену до мероприятия. Но не обязательно, что цена после мероприятия будет такая как до мероприятия. Важно учесть, что может быть просто изменение (повышение или понижение) цены без участия мероприятия, например, повышение цен из за инфляции.

Только вот пока затрудняюсь понять как это все сделать эскуэльно.
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619919
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkТогда для полей [Код ТТ пред] и [SKU пред] получается тоже надо писать так
Код: sql
1.
2.
LAG([Код ТТ]) OVER(Partition by [Клиент] ORDER BY [Код ТТ]) [Код ТТ пред],
LAG([SKU]) OVER(Partition by [Клиент],[Код ТТ] ORDER BY [SKU]) [SKU пред],


Верно или оставить как было?

Добавляя выражение "Partition by [Клиент],[Код ТТ],[SKU]" ограничиваем работу окна именно значениями из текущей строки.
Т.е. "LAG([Цена]) OVER(Partition by [Клиент],[Код ТТ],[SKU] ORDER BY [Дата])" можно перевести как:
Для текущих значений [Клиент],[Код ТТ],[SKU] найти предыдущее по [Дата] значение [Цена].
Так что проверка предыдущей строки на соответствие полей [Клиент],[Код ТТ],[SKU] не требуется.

Как определять "базовую" цену уточняй у постановщика задания.
Если все-таки нужно будет брать цену на начало года, то запросом собираешь таблицу базовых цен и все последующие даты/цены сравниваешь с ней...
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619935
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KopellyferzmikkТогда для полей [Код ТТ пред] и [SKU пред] получается тоже надо писать так
Код: sql
1.
2.
LAG([Код ТТ]) OVER(Partition by [Клиент] ORDER BY [Код ТТ]) [Код ТТ пред],
LAG([SKU]) OVER(Partition by [Клиент],[Код ТТ] ORDER BY [SKU]) [SKU пред],


Верно или оставить как было?

Добавляя выражение "Partition by [Клиент],[Код ТТ],[SKU]" ограничиваем работу окна именно значениями из текущей строки.
Т.е. "LAG([Цена]) OVER(Partition by [Клиент],[Код ТТ],[SKU] ORDER BY [Дата])" можно перевести как:
Для текущих значений [Клиент],[Код ТТ],[SKU] найти предыдущее по [Дата] значение [Цена].
Так что проверка предыдущей строки на соответствие полей [Клиент],[Код ТТ],[SKU] не требуется.
Проверка на соответствие я сделал для того, чтобы SQL понимал, что это другой TT+SKU и сравнивал цены только для соответствующих TT+SKU.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
...
                (CASE
                        --Если предыдущая строка это соответствующая ТТ+SKU
			WHEN [Код ТТ] = [Код ТТ пред] AND [SKU] = [SKU пред] THEN
				(CASE
                                        --Если цена одинаковая, но не мероприятие
					WHEN [Цена] = [Цена пред] THEN
						NUll
                                        --Если цена одинаковая, но мероприятие
					WHEN [Цена] = [Цена пред] THEN
						NUll
                                        --Если цена отличается
					ELSE
						(CASE
							WHEN [Цена] >= [Цена пред] THEN
								([Цена] - [Цена пред] )  /  [Цена пред]
							ELSE
								([Цена пред] - [Цена]) / [Цена]
						END)
				END)
			ELSE
			NULL
		END)
			[Дельта]
...


Я правильно понимаю, что достаточно так написать?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
...
SELECT
	[Клиент],
	[Код ТТ],	
	[SKU],
	[Дата],
	[Отгрузки шт],
	[Возвраты шт],
	[Реализация шт],
	[Реализация сумма без НДС],
	[Цена],
	LAG([Цена]) OVER(Partition by [Клиент],[Код ТТ],[SKU] ORDER BY  [Дата]) [Цена пред]
FROM
	@Таблица
...

...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39619945
Фотография Дедушка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkЯ правильно понимаю, что достаточно так написать?для решения исходной задачи ("нужно отметить те строки-дни, где было ценовое мероприятие") - нЕт.
вам уже несколько раз написали, уточните постановку, а именно что такое "ценовое мероприятие".
от ответа на это вопрос будет зависеть конкретный вариант решения.
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39620102
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дедушкауточните постановку, а именно что такое "ценовое мероприятие".
от ответа на это вопрос будет зависеть конкретный вариант решения.
Описываю развернуто.

Имеются исторические данные с января 2014 г. о продажах. Нужно провести прогнозирование, но этот вопрос в данном посте не рассматривается. В разные периоды присутствуют различные промо. При промо продажи обычно выше, различные всплески продаж. Чтобы убрать эти всплески нужно промаркировать дни, где было промо.

Промо бывает ценовое и не ценовое. Ценовое промо это когда в TT+SKU в какие то дни цена снижена. В данную задачу пока смотрим только ценовое промо.

Проблема в том, что для начала нужно определить базовую цену. Данные начинаются с 1.01.2014. г. Всегда это праздничный день. Тут могло быть либо утвержденное приказом ценовое промо (цена занижена), либо нет (просто народ закупает по обычной (базовой) цене в праздничный день, и продажи больше).

Решение по поводу определения базовой цены:
- Вариант 1, если фактически 1.01.2014 г. было ценовое промо. Тут для каждого ТТ+SKU для первых чисел января 2014 года это ценовое промо. И если на следующий какой то день цена повысится, то это будет базовая цена. Задать константу первые 15 дней.
- Вариант 2, если фактически 1.01.2014 г. не было ценового промо, народ просто закупает по базовой цене. Не придумал решение пока.

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

Для варианта 1 на скриншоте желтые ячейки это базовые цены. Так как цена отличается от предыдущей заданной выше предельной дельты, например, 15%.
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39620124
Фотография Дедушка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

для подобных задач только ценовых данных недостаточно нужно подключать другие данные учётных систем
(например 1С где фиксируются данные о закупочных ценах и промо акциях).

пример:
- 1го января привезли партию товара по цене 100 - для всего января "базовая" цена на этот товар = 100
- 1го февраля привезли новую партию этого же товара, но уже по цене 200 - для февраля базовая цена уже другая
- 10го февраля ввели акцию купи это товар на этой неделе со скидкой 50%, а на следующей уже будет только 20%
(т.е цена сначала снижена, а потом повысилась, но это всё ещё промо-цена)

НО с точки зрения исходной задачи - прогнозирования
точная "день в день" идентификация промо акций вовсе не нужна (это шум)
снижение цены на 10 рублей нивелируется в общем прогнозе
вам нужно просто удалить выбросы (существенное изменение цены)
по уму, это нужно делать с помощью медианы, квартилей и тд.
если же вы хотите прогнозировать "спрос" гуглите - "восстановление спроса".
...
Рейтинг: 0 / 0
Сравнение строк по заданным условиям
    #39620283
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkЯ правильно понимаю, что достаточно так написать?
Для определения предыдущей цены - да, правильно.

Я думаю что постановка которую ты описал не совсем корректна:
1. На начало года в теории может быть повышение цен для реализации товаров по каким-то временным бонусам.
2. Как определить базовую цену для товаров которые появились в течении года (они могли сразу попасть в какое-то ценовое событие).

Ну если реализовать под текущую постановку, то запрос для "базовой цены" можно реализовать так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
With Ordered as 
(Select Товар, Цена, Row_Number() Over (Partition by Товар Order by Дата desc) as RN From Цены Where Дата<=@НачалоГода)
Select Ordered.Товар, isnull(След.Цена,Ordered.Цена) as БазоваяЦена
From Ordered 
Outer apply 
(Select top 1 a.Цена
From Цены a 
Where a.Товар = Ordered.Товар and a.Дата>@НачалоГода and a.Дата <=DateAdd(dd,14,@НачалоГода)
and a.Цена>Ordered.Цена
Order by a.Data
) след
Where Ordered.RN = 1
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сравнение строк по заданным условиям
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]