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

Есть 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '04.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '05.01.2014', 100);

SELECT
	Т2.[Клиент],
	Т2.[Код юр лица],
	Т2.[Код ТТ],	
	Т2.[Код продукции],
	Т2.[Дата],
	Т2.[Цена],
	Т2.[Цена пред],		
	(CASE
		WHEN ([Цена пред] IS NOT NULL) AND (([Цена]/[Цена пред])-1) <= -@ДельтаПредел THEN
			1
		ELSE
			0
		END) AS [Маркировка скидки]
FROM
	(SELECT
		[Клиент],
		[Код юр лица],
		[Код ТТ],	
		[Код продукции],
		[Дата],
		[Цена],
		LAG([Цена]) OVER(Partition by [Клиент], [Код юр лица], [Код ТТ],[Код продукции] ORDER BY  [Дата]) AS [Цена пред]		
	FROM
		@Таблица
	/*ORDER BY
		[Клиент],
		[Код юр лица],
		[Код ТТ],	
		[Код продукции],
		[Дата]*/
	) AS Т2

Выдает такой результат
Клиент Код юр лица Код ТТ Код продукции Дата Цена Цена пред Маркировка скидкиКлиент Код юр лица1 Код ТТ1 SKU1 2014-01-01 100 NULL 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-02 100 100 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-03 80 100 1 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-04 80 80 0 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-05 100 80 0
Не обращайте внимание что название полей на русском языке, это для примера и для понятности. А также не придаем значение базовой цены. Просто сравниваем с предыдущей строкой.

На четвертой строке вместо 0 должен быть 1. А для этого нужно вытащить предыдущее значение вычисляемого поля Маркировка .

То есть написать типа так
SQL-Запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	(CASE
		WHEN ([Цена пред] IS NOT NULL) AND (([Цена]/[Цена пред])-1) <= -@ДельтаПредел THEN
			1
		ELSE
			(CASE
				WHEN  (([Цена]/[Цена пред])-1) <= @ДельтаПредел AND [Маркировка скидки пред] =1 THEN
					1
				ELSE
					0
				END)
			END)
		END) AS [Маркировка скидки]


1. Как вытягивать предыдущее значение вычисляемого поля?

2. Order By не работает во вложенном запросе. В рабочем коде используются табличные выражения и вложенные запросы. Как можно обойти эту проблему?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627595
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkКак вытягивать предыдущее значение вычисляемого поля?LEAD()

ferzmikkOrder By не работает во вложенном запросе.ORDER BY в промежуточных итогах используется только в том случае, когда влияет на список записей выходного набора. Без ограничения количества возвращаемых записей простая сортировка на набор не влияет - а потому игнорируется.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627616
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaferzmikkКак вытягивать предыдущее значение вычисляемого поля?LEAD()
LEAD вытягивает из последующей строки, а надо из предыдущей. А также по текущей строке при расчете вычисляемого поля [Маркировка скидки] нужно вытянуть рассчитанное значение этого же поля предыдущей строки.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627618
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaferzmikkOrder By не работает во вложенном запросе.ORDER BY в промежуточных итогах используется только в том случае, когда влияет на список записей выходного набора. Без ограничения количества возвращаемых записей простая сортировка на набор не влияет - а потому игнорируется.
Поскольку во вложенном запросе я использую оконную функция Lag, то актуально делать сортировку, если я не ошибаюсь.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627621
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkПоскольку во вложенном запросе я использую оконную функция Lag, то актуально делать сортировку, если я не ошибаюсь.LAG() имеет свой собственный класс ORDER BY и не зависит от внешнего.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627629
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkAkinaпропущено...
LEAD()
LEAD вытягивает из последующей строки, а надо из предыдущей. А также по текущей строке при расчете вычисляемого поля [Маркировка скидки] нужно вытянуть рассчитанное значение этого же поля предыдущей строки.
А тут как?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627635
Фотография Дедушка
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkА тут как?делать в два прохода
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627657
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут расчет получается последовательным как в excel.

На скриншоте для ячейки P14 нужно выйти на P13, для P15 нужно выйти на P14.

Никак получается.

Как написать запрос?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627659
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkКак написать запрос?"рекурсивно",
в смысле рекурсивный запрос :)
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627661
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtferzmikkКак написать запрос?"рекурсивно",
в смысле рекурсивный запрос :)
Код: 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '04.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '05.01.2014', 100);

;with T as (
	select *, id=ROW_NUMBER()over(order by [Дата]) from @Таблица),
cte as (
	select *, cast(null as numeric(8,0)) as [Цена пред], 0 as [Маркировка скидки] from T
	where id=1
	
	union all
	
	select t.*, cte.[Цена], 
		CASE
			WHEN ([Цена пред] IS NOT NULL) AND ((t.Цена/[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END
	
		
		from cte inner join t on t.id=cte.id+1)
		
select * from cte order by id			



КлиентКод юр лицаКод ТТКод продукцииДатаЦенаidЦена предМаркировка скидкиКлиентКод юр лица1Код ТТ1SKU12014-01-011001NULL0КлиентКод юр лица1Код ТТ1SKU12014-01-0210021000КлиентКод юр лица1Код ТТ1SKU12014-01-038031001КлиентКод юр лица1Код ТТ1SKU12014-01-04804801КлиентКод юр лица1Код ТТ1SKU12014-01-051005800
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627664
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Спасибо, буду разбирать!
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627685
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
with t as
(
 select
  *,
  LAG([Цена], 1) OVER(Partition by [Клиент], [Код юр лица], [Код ТТ],[Код продукции] ORDER BY  [Дата]) as p1,
  LAG([Цена], 2) OVER(Partition by [Клиент], [Код юр лица], [Код ТТ],[Код продукции] ORDER BY  [Дата]) as p2
 from
  @Таблица
)
select
 Клиент,
 [Код юр лица],
 [Код ТТ],
 [Код продукции],
 Дата,
 Цена,
 p1 as [Цена пред],
 case
  when p1/p2 - 1 <= -@ДельтаПредел or [Цена]/p1 - 1 <= -@ДельтаПредел then 1
  else 0
 end
from
 t;

?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627732
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

Если добавить еще строки в исходных данных

Код: 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '04.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '05.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '06.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '07.01.2014', 100);

with t as
(
 select
  *,
  LAG([Цена], 1) OVER(Partition by [Клиент], [Код юр лица], [Код ТТ],[Код продукции] ORDER BY  [Дата]) as p1,
  LAG([Цена], 2) OVER(Partition by [Клиент], [Код юр лица], [Код ТТ],[Код продукции] ORDER BY  [Дата]) as p2
 from
  @Таблица
)
select
 Клиент,
 [Код юр лица],
 [Код ТТ],
 [Код продукции],
 Дата,
 Цена,
 p1 as [Цена пред],
 case
  when p1/p2 - 1 <= -@ДельтаПредел or [Цена]/p1 - 1 <= -@ДельтаПредел then 1
  else 0
 end
from
 t;

то результат будет таким
Клиент Код юр лица Код ТТ Код продукции Дата Цена Цена пред (Отсутствует имя столбца)Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-01 100 NULL 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-02 100 100 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-03 80 100 1Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-04 80 80 1Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-05 80 80 0 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-06 80 80 0 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-07 100 80 0
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627734
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

При таком запросе
Код: 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '06.01.2014', 100);
;

WITH T as (
	SELECT
		*,
		id=ROW_NUMBER()over(order by [Клиент], [Код юр лица], [Код ТТ], [Код продукции], [Дата]) from @Таблица),
		cte as (
			select
				*,
				cast(null as numeric(8,0)) as [Цена пред],
				0 as [Маркировка скидки]
			from
				T
			where
				id=1	
	union all
	
	select
		t.*,
		cte.[Цена], 
		CASE
			WHEN ([Цена пред] IS NOT NULL) AND ((t.Цена/[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END
	
		
		from cte inner join t on t.id=cte.id+1)
		
select * from cte order by id	

выдает такой результат
Клиент Код юр лица Код ТТ Код продукции Дата Цена id Цена пред Маркировка скидкиКлиент Код юр лица1 Код ТТ1 SKU1 2014-01-01 100 1 NULL 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-02 100 2 100 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-03 80 3 100 1 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-06 100 4 80 1
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627736
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

И еще, при использовании рекурсии, когда много строк, то запрос намного дольше выполянется. Возможно ли как то ускорить?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627743
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkcourt,

И еще, при использовании рекурсии, когда много строк, то запрос намного дольше выполянется. Возможно ли как то ускорить?
165 строк - 2 мин 36 сек
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627780
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkcourt,

При таком запросе
Код: 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 100),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент', 'Код юр лица1', 'Код ТТ1','SKU1', '06.01.2014', 100);
;

WITH T as (
	SELECT
		*,
		id=ROW_NUMBER()over(order by [Клиент], [Код юр лица], [Код ТТ], [Код продукции], [Дата]) from @Таблица),
		cte as (
			select
				*,
				cast(null as numeric(8,0)) as [Цена пред],
				0 as [Маркировка скидки]
			from
				T
			where
				id=1	
	union all
	
	select
		t.*,
		cte.[Цена], 
		CASE
			WHEN ([Цена пред] IS NOT NULL) AND ((t.Цена/[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END
	
		
		from cte inner join t on t.id=cte.id+1)
		
select * from cte order by id	


выдает такой результат
Клиент Код юр лица Код ТТ Код продукции Дата Цена id Цена пред Маркировка скидкиКлиент Код юр лица1 Код ТТ1 SKU1 2014-01-01 100 1 NULL 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-02 100 2 100 0Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-03 80 3 100 1 Клиент Код юр лица1 Код ТТ1 SKU1 2014-01-06 100 4 80 1 это исправь (желтым выделено)
Код: 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.
WITH T as (
	SELECT
		*,
		id=ROW_NUMBER()over(order by [Клиент], [Код юр лица], [Код ТТ], [Код продукции], [Дата]) from @Таблица),
		cte as (
			select
				*,
				t.[Цена] as [Цена пред],	--cast(null as numeric(8,0)) as [Цена пред],
				0 as [Маркировка скидки]
				,[Цена пред которая используется в расчете]=cast(null as numeric(8,0))
			from
				T
			where
				id=1	
	union all
	
	select
		t.*,
		t.[Цена], -- cte.[Цена], 
		CASE
			WHEN ([Цена пред] IS NOT NULL) AND ((1.0*t.Цена/[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END
		,cte.[Цена пред]
		
	from cte inner join t on t.id=cte.id+1)
		
select * from cte order by id



[Цена пред которая используется в расчете] - это для понимания, что там вообще происходит, если нужно
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627864
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

В условном примере правильно работает, а в рабочем - не правильно. Не могу понять.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627873
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627874
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkcourt,

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


а так
Код: sql
1.
LAG([Цена]) OVER(Partition by [Клиент],[Код юрлица],[Код ТТ],[Код продукции] ORDER BY Convert(datetime,[Дата],104) ) [Цена пред]


и из за этого неправильно сортировался, следовательно, неправильно маркировались.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39627948
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Из за рекурсии подтормаживает сильно. Возможно ли как то ускорить выгрузку?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39628022
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkИз за рекурсии подтормаживает сильно. Возможно ли как то ускорить выгрузку?
65000 строк. Обрабатывает более 2 часов.

Может быть в ON еще связку указать?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39628957
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обнаружил не учтенный момент.
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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '06.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '01.01.2014', 50),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '02.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '06.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '01.01.2014', 60),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '02.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '06.01.2014', 100);

WITH T AS (
	SELECT
		*,
		id=ROW_NUMBER()over(order by [Клиент], [Код юр лица], [Код ТТ], [Код продукции], [Дата]) from @Таблица),
		cte as (
			select
				*,
				t.Цена as [Цена пред],
				0 as [Маркировка скидки],
				[Цена пред которая используется в расчете]=cast(null as numeric(8,0))
			from
				T
			where
				id=1	
	UNION ALL	
	SELECT
		t.*,
		t.[Цена], 
		CASE
			WHEN (cte.[Цена пред] IS NOT NULL) AND ((t.[Цена]/cte.[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/cte.[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END,
		cte.[Цена пред]	
	FROM
		cte
	INNER JOIN
		t
	ON
		t.id=cte.id+1)
		
SELECT
	*
FROM
	cte
ORDER BY
	id	

выдает такой результат:
Результат запросаКлиент Код юр лица Код ТТ Код продукции Дата Цена id Цена пред Маркировка скидки Цена пред кот исполь в расчКлиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-01 100 1 100 0 NULLКлиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-02 80 2 80 1 100Клиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-03 80 3 80 1 80Клиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-04 80 4 80 1 80Клиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-05 100 5 100 0 80Клиент1 Код юр лица1 Код ТТ1 SKU1 2014-01-06 100 6 100 0 100Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-01 50 7 50 1 100Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-02 100 8 100 0 50Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-03 80 9 80 1 100Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-04 80 10 80 1 80Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-05 100 11 100 0 80Клиент1 Код юр лица1 Код ТТ1 SKU2 2014-01-06 100 12 100 0 100Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-01 60 13 60 1 100Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-02 100 14 100 0 60Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-03 80 15 80 1 100Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-04 80 16 80 1 80Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-05 100 17 100 0 80Клиент1 Код юр лица1 Код ТТ2 SKU1 2014-01-06 100 18 100 0 100

Если на следующей строке другая группа, то есть другое SKU, другая ТТ, то предыдущую цену и предыдущую маркировку смотреть не нужно. Для этой же строки в поле Маркировка скидки сразу возвращает ноль. Как правильно дописать запрос?

И еще. В поле Цена пред отображается текущая цена, но не предыдущая. Почему так?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39628969
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

Код: sql
1.
id=ROW_NUMBER()over(Partition by [Клиент], [Код юр лица], [Код ТТ], [Код продукции] order by  [Дата]) from @Таблица)



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
FROM
		cte
	INNER JOIN
		t
	ON
		t.id=cte.id+1 and 
		t.[Клиент]=cte.[Клиент] and 
		t.[Код юр лица]=cte.[Код юр лица] and 
		t.[Код ТТ]=cte.[Код ТТ] and 
		t.[Код продукции]=cte.[Код продукции]
	and 
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39628970
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще и быстрее будет выполняться
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39628987
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kopelly,

Я правильно понимаю, что поле [Цена пред которая используется в расчете] можно смело брать как предыдущая цена?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629003
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

В конечном результате [Цена пред которая используется в расчете] - цена предыдущего шага.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629084
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kopelly,

В конечном итоге не сортируется. Получается надо так писать
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.
Declare @ДельтаПредел decimal(5,2) = 0.07;
DECLARE @Таблица table(	
	[Клиент] varchar(8),
	[Код юр лица] varchar(12),
	[Код ТТ] varchar(8),	
	[Код продукции] varchar(8),
	[Дата] date,
	[Цена] numeric(8,0)
	)	
;

INSERT INTO
  @Таблица
VALUES 
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '01.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '02.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU1', '06.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '01.01.2014', 50),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '02.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ1','SKU2', '06.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '01.01.2014', 60),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '02.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '03.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '04.01.2014', 80),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '05.01.2014', 100),
('Клиент1', 'Код юр лица1', 'Код ТТ2','SKU1', '06.01.2014', 100);

WITH T AS (
	SELECT
		*,
		--id=ROW_NUMBER()over(order by [Клиент], [Код юр лица], [Код ТТ], [Код продукции], [Дата]) from @Таблица),
		id=ROW_NUMBER()over(Partition by [Клиент], [Код юр лица], [Код ТТ], [Код продукции] order by Convert(datetime,[Дата],104)) from @Таблица),
		cte as (
			select
				*,
				t.Цена as [Цена пред],
				0 as [Маркировка скидки],
				[Цена пред которая используется в расчете]=cast(null as numeric(8,0))
			from
				T
			where
				id=1	
	UNION ALL	
	SELECT
		t.*,
		t.[Цена], 
		CASE
			WHEN (cte.[Цена пред] IS NOT NULL) AND ((t.[Цена]/cte.[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/cte.[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка скидки] =1 THEN
						1
					ELSE
						0
				END
		END,
		cte.[Цена пред]	
	FROM
		t
	INNER JOIN
		cte
	ON
		t.id=cte.id+1
		AND 
		t.[Клиент]=cte.[Клиент]
		AND 
		t.[Код юр лица]=cte.[Код юр лица]
		AND
		t.[Код ТТ]=cte.[Код ТТ]
		AND
		t.[Код продукции]=cte.[Код продукции])
		
SELECT
	*
FROM
	cte
ORDER BY
	--id
	[Клиент],
	[Код юр лица],
	[Код ТТ],
	[Код продукции],
	Convert(datetime,[Дата],104) 


Или так
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
...
ORDER BY	
	[Клиент],
	[Код юр лица],
	[Код ТТ],
	[Код продукции],
	id
...
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629153
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kopellyferzmikk,

Код: sql
1.
id=ROW_NUMBER()over(Partition by [Клиент], [Код юр лица], [Код ТТ], [Код продукции] order by  [Дата]) from @Таблица)



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
FROM
		cte
	INNER JOIN
		t
	ON
		t.id=cte.id+1 and 
		t.[Клиент]=cte.[Клиент] and 
		t.[Код юр лица]=cte.[Код юр лица] and 
		t.[Код ТТ]=cte.[Код ТТ] and 
		t.[Код продукции]=cte.[Код продукции]
	and 


KopellyЕще и быстрее будет выполняться
Перевел на рабочий код, только быстрее не стало, а наоборот. Будто где то упустили запись.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629155
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
35 строк - 4 мин 40 сек.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629190
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Рабочий код

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.
109.
110.
111.
112.
113.
Declare @ДельтаПредел decimal(5,2) = 0.07;

WITH
	TempTable1 AS (
	SELECT
		CAST(F1."[Торговые точки].[Клиент].[Клиент].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Клиент],
		CAST(F1."[Торговые точки].[Код юрлица].[Код юрлица].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код юрлица],
		CAST(F1."[Торговые точки].[Код ТТ].[Код ТТ].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код ТТ],
		CAST(F1."[Продукция].[Код продукции].[Код продукции].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код продукции],	
		CONVERT(nvarchar(10), F1."[Время].[Дата].[Дата].[MEMBER_CAPTION]" , 104) AS [Дата],
		F1."[Measures].[Отгрузки шт]" AS [Отгрузки шт],
		F1."[Measures].[Возвраты шт]" AS [Возвраты шт],
		F1."[Measures].[Реализация шт]" AS [Реализация шт],
		CAST(F1."[Measures].[Отгрузки сумма без НДС]" AS float) AS [Отгрузки сумма без НДС],
		CAST(F1."[Measures].[Цена]"  AS decimal(10,0)) AS [Цена]
		FROM OPENROWSET(
		'MSOLAP',
		'Provider=MSOLAP.3;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=profit;Data Source=...;MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error',
		'WITH
			MEMBER [Measures].[Цена] AS (CASE
				WHEN [Measures].[Отгрузки шт] <>0 THEN
						[Measures].[Отгрузки сумма без НДС] / [Measures].[Отгрузки шт]
				END)
			SELECT
				{[Measures].[Отгрузки шт],
				[Measures].[Возвраты шт],	
				[Measures].[Реализация шт],
				[Measures].[Отгрузки сумма без НДС],
				[Measures].[Цена]}
			ON 0,
			NON EMPTY
				[Торговые точки].[Клиент].[Клиент]*
				[Торговые точки].[Код юрлица].[Код юрлица]*
				[Торговые точки].[Код ТТ].[Код ТТ]*
				[Продукция].[Код продукции].[Код продукции]*
				[Время].[Дата].[Дата]
			ON 1
			FROM
				(SELECT
					([Время].[Месяц].&[2017-01-01T00:00:00]:[Время].[Месяц].&[2017-12-01T00:00:00],					
					,[Продукция].[Код продукции].&[13163]
					,{[Торговые точки].[Код ТТ].&[00008грд]}
					) ON 0 FROM PROFIT)'
		) AS F1
	),

TempTable2 AS (
	SELECT
		[Клиент],
		[Код юрлица],
		[Код ТТ],
		[Код продукции],	
		[Дата],
		[Отгрузки шт],
		[Возвраты шт],
		[Реализация шт],
		[Отгрузки сумма без НДС],
		[Цена],
		Year([Дата]) AS [Год],
		Month ([Дата]) AS [Месяц]
	FROM
		TempTable1
	WHERE		
		NOT([Отгрузки шт] =0)
),

	T as (
	SELECT
		*,
		--id=ROW_NUMBER()over(order by [Клиент], [Код юрлица], [Код ТТ], [Код продукции], Convert(datetime,[Дата],104)) FROM TempTable2 ),
		id=ROW_NUMBER()over(Partition by [Клиент], [Код юрлица], [Код ТТ], [Код продукции] order by  Convert(datetime,[Дата],104)) from TempTable2),
		cte AS (
			SELECT
				*,
				t.[Цена] AS [Цена пред],
				0 AS [Маркировка по пред цене],
				[Цена пред которая используется в расчете]=cast(null as decimal(10,0))
			FROM
				T
			WHERE
				id=1
	UNION ALL	
	SELECT
		t.*,
		t.[Цена], 
		CASE
			WHEN (cte.[Цена пред] IS NOT NULL) AND ((t.Цена/cte.[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/cte.[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка по пред цене] =1 THEN
						1
					ELSE
						0
				END
		END,
		cte.[Цена пред]
	FROM
		t
	inner join
		cte
	ON
		t.id=cte.id+1
		AND
		t.[Клиент]=cte.[Клиент]
		AND 
		t.[Код юрлица]=cte.[Код юрлица]
		AND 
		t.[Код ТТ]=cte.[Код ТТ]
		AND 
		t.[Код продукции]=cte.[Код продукции]  )

SELECT * FROM cte ORDER BY  [Клиент], [Код юрлица], [Код ТТ], [Код продукции], id

Затрудняюсь его оптимизировать.

Как можно еще оптимизировать или уже никак?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629194
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

через времянку эту свою TempTable1 сделай
А дальше уже ЦТЕ
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629202
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtferzmikk,

через времянку эту свою TempTable1 сделай
А дальше уже ЦТЕ
Я правильно понимаю, что TempTable1 толкать непосредственно в таблицу базы данных, и потом cte толкать в другую таблицу?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629204
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtferzmikk,

через времянку эту свою TempTable1 сделай
А дальше уже ЦТЕ
Даже не так
К этому "месту" твоего кода
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
		cte AS (
			SELECT
				*,
				t.[Цена] AS [Цена пред],
				0 AS [Маркировка по пред цене],
				[Цена пред которая используется в расчете]=cast(null as decimal(10,0))
			FROM
				T
			WHERE
				id=1
	UNION ALL	
.... 


ты должен прийти с "настоящей" (пусть временной) таблицей T (#T)

и, по вкусу, индекс на [Клиент], [Код юр лица], [Код ТТ], [Код продукции], id
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629214
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikk,

вот что-то типа этого должно быть
Код: 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.
Declare @ДельтаПредел decimal(5,2) = 0.07;

--	1
	SELECT
		CAST(F1."[Торговые точки].[Клиент].[Клиент].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Клиент],
		CAST(F1."[Торговые точки].[Код юрлица].[Код юрлица].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код юрлица],
		CAST(F1."[Торговые точки].[Код ТТ].[Код ТТ].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код ТТ],
		CAST(F1."[Продукция].[Код продукции].[Код продукции].[MEMBER_CAPTION]" AS VARCHAR(20)) AS [Код продукции],	
		CONVERT(nvarchar(10), F1."[Время].[Дата].[Дата].[MEMBER_CAPTION]" , 104) AS [Дата],
		F1."[Measures].[Отгрузки шт]" AS [Отгрузки шт],
		F1."[Measures].[Возвраты шт]" AS [Возвраты шт],
		F1."[Measures].[Реализация шт]" AS [Реализация шт],
		CAST(F1."[Measures].[Отгрузки сумма без НДС]" AS float) AS [Отгрузки сумма без НДС],
		CAST(F1."[Measures].[Цена]"  AS decimal(10,0)) AS [Цена]

into #TempTable1
		FROM OPENROWSET(
		'MSOLAP',
		'Provider=MSOLAP.3;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=profit;Data Source=...;MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error',
		'WITH
			MEMBER [Measures].[Цена] AS (CASE
				WHEN [Measures].[Отгрузки шт] <>0 THEN
						[Measures].[Отгрузки сумма без НДС] / [Measures].[Отгрузки шт]
				END)
			SELECT
				{[Measures].[Отгрузки шт],
				[Measures].[Возвраты шт],	
				[Measures].[Реализация шт],
				[Measures].[Отгрузки сумма без НДС],
				[Measures].[Цена]}
			ON 0,
			NON EMPTY
				[Торговые точки].[Клиент].[Клиент]*
				[Торговые точки].[Код юрлица].[Код юрлица]*
				[Торговые точки].[Код ТТ].[Код ТТ]*
				[Продукция].[Код продукции].[Код продукции]*
				[Время].[Дата].[Дата]
			ON 1
			FROM
				(SELECT
					([Время].[Месяц].&[2017-01-01T00:00:00]:[Время].[Месяц].&[2017-12-01T00:00:00],					
					,[Продукция].[Код продукции].&[13163]
					,{[Торговые точки].[Код ТТ].&[00008грд]}
					) ON 0 FROM PROFIT)'
		) AS F1

--	2
delete from #TempTable1 where ([Отгрузки шт] =0)

--	3
SELECT
	*,
	id=ROW_NUMBER()over(Partition by [Клиент], [Код юрлица], [Код ТТ], [Код продукции] order by  Convert(datetime,[Дата],104)) 

into #T
		
from TempTable1

--	???
-- CREATE /*CLUSTERED*/ INDEX i1 ON #T ([Клиент], [Код юрлица], [Код ТТ], [Код продукции], id);  

--	4
;with	cte AS (
	SELECT
		*,
		t.[Цена] AS [Цена пред],
		0 AS [Маркировка по пред цене],
		[Цена пред которая используется в расчете]=cast(null as decimal(10,0))
	FROM
		#T t
	WHERE
		id=1

	UNION ALL
		
	SELECT
		t.*,
		t.[Цена], 
		CASE
			WHEN (cte.[Цена пред] IS NOT NULL) AND ((t.Цена/cte.[Цена пред])-1) <= -@ДельтаПредел THEN
				1
			ELSE
				CASE
					WHEN  ((t.[Цена]/cte.[Цена пред])-1) <= @ДельтаПредел AND cte.[Маркировка по пред цене] =1 THEN
						1
					ELSE
						0
				END
		END,
		cte.[Цена пред]
	FROM
		#T t
	inner join
		cte
	ON
		t.id=cte.id+1
		AND
		t.[Клиент]=cte.[Клиент]
		AND 
		t.[Код юрлица]=cte.[Код юрлица]
		AND 
		t.[Код ТТ]=cte.[Код ТТ]
		AND 
		t.[Код продукции]=cte.[Код продукции]  )

SELECT * FROM cte ORDER BY  [Клиент], [Код юрлица], [Код ТТ], [Код продукции], id

...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629225
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtты должен прийти с "настоящей" (пусть временной) таблицей T (#T)

и, по вкусу, индекс на [Клиент], [Код юр лица], [Код ТТ], [Код продукции], id
Смысл использовать временную таблицу, если есть табличные переменные TempTable1 и cte? Неужели такой подход значительно увеличит время выгрузки, если используем рекурсию? Только вот такие временные таблицы я еще не создавал, следовательно, затрудняюсь в понимании как их делать.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629227
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtferzmikk,

вот что-то типа этого должно быть

Я правильно понимаю, что нужны еще отдельные запросы по созданию таких временных таблиц? Или в базе данных ничего создавать не нужно и базу данных якобы не трогаем?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629231
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkcourtты должен прийти с "настоящей" (пусть временной) таблицей T (#T)

и, по вкусу, индекс на [Клиент], [Код юр лица], [Код ТТ], [Код продукции], id
Смысл использовать временную таблицу, если есть табличные переменные TempTable1 и cte? Неужели такой подход значительно увеличит время выгрузки, если используем рекурсию? Только вот такие временные таблицы я еще не создавал, следовательно, затрудняюсь в понимании как их делать.это не табличные переменные

// затрудняюсь

выше, полностью готовый скрипт на твоих данных
добавь ещё в конце

Код: sql
1.
drop table #TempTable1, #T


и запускай

Будет не удовлетворительно по времени, - ещё с индексом можно "поиграться"
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39629676
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

А если сохранять не во временную таблицу, а в саму таблицу в базу данных (и она как бы и временная)? То вроде должно быть быстрее.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39635464
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем тормозит именно из за этого
Код: sql
1.
SELECT * FROM cte ORDER BY  [Клиент], [Код юрлица], [Код ТТ], [Код продукции], id


Как можно ускорить? Или все равно надо иcпользовать временную таблицу с индексами?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39635534
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkВ общем тормозит именно из за этого
Код: sql
1.
SELECT * FROM cte ORDER BY  [Клиент], [Код юрлица], [Код ТТ], [Код продукции], id


Как можно ускорить? Или все равно надо иcпользовать временную таблицу с индексами?
И еще
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
WITH	
TempTable1 AS (
	SELECT
		[Клиент],
		[Код юрлица],
		[Код ТТ],
		[Код продукции],	
		[Дата],
		[Отгрузки шт],
		[Возвраты шт],
		[Реализация шт],
		[Отгрузки сумма без НДС],		
		[Цена без НДС]			
	FROM
		Shipments	
	WHERE
		[Код ТТ]=N'00001грд'
...


В таблице Shipments 6 миллионов строк. Я думаю, что при отборе через WHERE подтормаживает сильно.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39636370
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
courtвыше, полностью готовый скрипт на твоих данных
добавь ещё в конце
Код: sql
1.
drop table #TempTable1, #T


и запускай

Будет не удовлетворительно по времени, - ещё с индексом можно "поиграться"
Разобрался с временными таблицами. Результат стал намного удовлетворительным. 6 млн строк за 40 минут.

Дальше в коде после рекурсии используются последующие табличные переменные (без использования рекурсии). Если их заменить временными таблицами, то еще быстрее будет работать?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39637473
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Присутствует поле [Маркировка по пред цене]. Теперь надо добавить поле [Маркировка по посл цене], который идет снизу вверх.
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.
Declare @ДельтаПредел decimal(5,2) = 0.07;

SELECT
	[Клиент],
	[Код юрлица],
	[Код ТТ],
	[Код продукции],	
	[Дата],
	[Отгрузки шт],
	[Возвраты шт],
	[Реализация шт],
	[Отгрузки сумма без НДС],
	[Отгрузки сумма с НДС],
	[Расчетная цена без НДС],
	[Расчетная цена с НДС],
	id=ROW_NUMBER()over(Partition by [Клиент], [Код юрлица], [Код ТТ], [Код продукции] order by  Convert(datetime,[Дата],104)),
	id2=ROW_NUMBER()over(Partition by [Клиент], [Код юрлица], [Код ТТ], [Код продукции] order by  Convert(datetime,[Дата],104)DESC)
INTO
	#Т
FROM
	Shipments		
;
CREATE /*CLUSTERED*/ INDEX i1 ON #Т([Клиент], [Код юрлица], [Код ТТ], [Код продукции], id); 
WITH
	cte AS (
		SELECT
			*,
			т.[Расчетная цена без НДС] AS [Расчетная цена без НДС пред],
			0 AS [Маркировка по пред цене],
			[Расчетная цена без НДС пред которая используется в расчете]=cast(null as decimal(8,0))
		FROM
			#Т т 
		WHERE
			id=1
	UNION ALL	
	SELECT
		т.*,
		т.[Расчетная цена без НДС], 
		CASE
			WHEN cte.[Расчетная цена без НДС пред] IS NOT NULL AND cte.[Расчетная цена без НДС пред] <> 0 THEN
				CASE
					WHEN ((т.[Расчетная цена без НДС] / cte.[Расчетная цена без НДС пред])-1) <= -@ДельтаПредел THEN
						1
					ELSE
						CASE
							WHEN  ((т.[Расчетная цена без НДС] / cte.[Расчетная цена без НДС пред])-1) <= @ДельтаПредел AND cte.[Маркировка по пред цене] =1 THEN
								1
							ELSE
								0
							END
				END
		END,
		cte.[Расчетная цена без НДС пред]
	FROM
		#Т т 
	inner join
		cte
	ON
		т.id=cte.id+1
		AND
		т.[Клиент]=cte.[Клиент]
		AND 
		т.[Код юрлица]=cte.[Код юрлица]
		AND 
		т.[Код ТТ]=cte.[Код ТТ]
		AND 
		т.[Код продукции]=cte.[Код продукции]
),

Как лучше сделать? Получить отдельно cte2 (обращается к id2), и потом соединить cte и cte2?
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39638099
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ferzmikkДальше в коде после рекурсии используются последующие табличные переменные (без использования рекурсии). Если их заменить временными таблицами, то еще быстрее будет работать?
Заменил все табличные переменные на временные таблицы. Стало работать намного быстрее.
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39638100
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Спасибо!
...
Рейтинг: 0 / 0
Предыдущее значение вычисляемого поля
    #39638101
ferzmikk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но задачка интересная очень вот!)
...
Рейтинг: 0 / 0
46 сообщений из 46, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Предыдущее значение вычисляемого поля
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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