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

Откуда:
Сообщений: 29
Суть вопроса.

Есть таблица Tbl_A. Следующей структуры:
TABLE [dbo].[Tbl_A](
	[IDTbl_A] [int] IDENTITY(1,1) NOT NULL,
	[KodProdukt] [int] NOT NULL,
	[KodIB] [int] NOT NULL,
	[KodSort] [int] NOT NULL CONSTRAINT [DF_Tbl_A_KodSort]  DEFAULT ((999))
) ON [PRIMARY]


Необходимо в нее вставить данные, но так что бы у всех последующих элементов, KodSort инкрементировался (до первого пробела. внутри KodProdukt)

например есть набор:
KodProduktKodIBKodSort
2101041
23025140
2303041
2304442
23024643
2305048
2422130


При вставке
SET @KodProdukt = 230
SET @KodIB = 254
SET @KOdSort = 41

Должно получиться так:
KodProduktKodIBKodSort
2101041
23025140
23025441
2303042
2304443
23024644
2305048
2422130


Так вот собственно, я смог придумать только связку курсор+временная таблица. Но меня этот метод сильно расстраивает.
Может кто-то предложит более оптимальное решение?

DECLARE @KodProdukt int, @KodIB int, @KodSort int, @tKodSort int

SET @KodProdukt = 230
SET @KodIB = 254
SET @KOdSort = 41

SET @tKodSort = @KodSort

-----------------

IF EXISTS (SELECT [KodProdukt], [KodIB] FROM [dbo].[Tbl_A] WHERE [KodProdukt] = @KodProdukt AND [KodIB] = @KodIB) BEGIN
  UPDATE [dbo].[Tbl_A] SET [KodSort] = @KodSort
    WHERE KOdProdukt = @KodProdukt and KodIB = @KodIB
END
ELSE
BEGIN
  INSERT INTO [dbo].[Tbl_A] 
  	([KodProdukt], [KodIB], [KodSort])
  VALUES
  	(@KodProdukt, @KodIB, @KodSort)
END



-----------------

DECLARE @CurIDTbl_A int, @CurKodSort int, @CntRec int

if OBJECT_ID('tempdb..##Tmp_IDTbl_A')>0 exec('drop table ##Tmp_IDTbl_A')
CREATE TABLE ##Tmp_IDTbl_A (IDTbl_A int)

DECLARE #Tmp_Tbl_A
CURSOR FOR 
	SELECT IDTbl_A
	FROM Tbl_A
	WHERE (KodProdukt = @KodProdukt) AND (KodSort >= @KodSort) AND (KodSort < 10000)
	ORDER BY KodSort

OPEN #Tmp_Tbl_A

FETCH NEXT FROM #Tmp_Tbl_A INTO @CurIDTbl_A

WHILE (@@FETCH_STATUS=0) AND (@tKodSort > 0) BEGIN
	SELECT @CntRec = COUNT(*) 
		FROM Tbl_A
		WHERE (KodProdukt = @KodProdukt) and (KodSort = @tKodSort)

	IF @CntRec >= 1 BEGIN
		INSERT INTO ##Tmp_IDTbl_A (IDTbl_A) Values(@CurIDTbl_A)
		SET @tKodSort = @tKodSort + 1
	END
	ELSE SET @tKodSort = 0

	FETCH NEXT FROM #Tmp_Tbl_A INTO @CurIDTbl_A
END

DEALLOCATE #Tmp_Tbl_A

UPDATE Tbl_A SET KodSort = KodSort + 1 where IDTbl_A in (Select IDTbl_A FROM ##Tmp_IDTbl_A)

if OBJECT_ID('tempdb..##Tmp_IDTbl_A')>0 exec('drop table ##Tmp_IDTbl_A')
1 июл 14, 09:29    [16241785]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 658
vrtlpilot,

Если я все правильно напутал, то
UPDATE [a]
    SET [KodSort] = [a].[KodSort] + 1
    FROM [dbo].[Tbl_A] [a]
    WHERE [a].[KodProdukt] = @KodProdukt
      AND [a].[KodSort] >= @KOdSort
;

А потом уже инсерт
1 июл 14, 10:57    [16242261]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
vrtlpilot
Member

Откуда:
Сообщений: 29
Guf
vrtlpilot,

Если я все правильно напутал, то
UPDATE [a]
    SET [KodSort] = [a].[KodSort] + 1
    FROM [dbo].[Tbl_A] [a]
    WHERE [a].[KodProdukt] = @KodProdukt
      AND [a].[KodSort] >= @KOdSort
;

А потом уже инсерт


Я тоже так подумал, но нельзя допускать дублирования KodSort внутри группы.
1 июл 14, 11:27    [16242462]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 658
vrtlpilot,

А где дублирование, если Вы сначала сдвинете пололовину кодов сортировки, а потом в образовавшуюся дырку вставите новый? Дырки допускаются?

P.S. про транзакции и все такое, надеюсь, не надо объяснять?
1 июл 14, 11:33    [16242506]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
vrtlpilot
Member

Откуда:
Сообщений: 29
Guf
vrtlpilot,
А где дублирование, если Вы сначала сдвинете пололовину кодов сортировки, а потом в образовавшуюся дырку вставите новый?

Верно. Сдвинутся все коды, а мне нужно до первой дырки. (как в примере)
Guf
Дырки допускаются?

И, да, дырки допускаются.
1 июл 14, 12:12    [16242816]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
Minamoto
Member

Откуда: Москва
Сообщений: 1162
vrtlpilot
Верно. Сдвинутся все коды, а мне нужно до первой дырки. (как в примере)

Ну добавьте туда INNER JOIN [dbo].[Tbl_A] [b] on [a].[KodProdukt] = [b].[KodProdukt] AND [a].[KodSort] + 1 = [b].[KodSort]
и в where >= замените на [a].[KodProdukt] + 1 = @KOdSort, чтобы ближнюю дырку исключить.
1 июл 14, 12:19    [16242873]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
invm
Member

Откуда: Москва
Сообщений: 9633
vrtlpilot
Сдвинутся все коды, а мне нужно до первой дырки. (как в примере)
UPDATE [a]
    SET [KodSort] = [a].[KodSort] + 1
    FROM [dbo].[Tbl_A] [a]
    WHERE [a].[KodProdukt] = @KodProdukt
      AND [a].[KodSort] >= @KOdSort
      and exists(select 1 from [dbo].[Tbl_A] where [KodProdukt] = [a].[KodProdukt] and [KodSort] = [a].[KodSort] + 1)
;
1 июл 14, 12:20    [16242885]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 658
vrtlpilot
Верно. Сдвинутся все коды, а мне нужно до первой дырки. (как в примере)

Тогда можно воспользоваться поиском и выбрать любой вариант на свой вкус.
Тогда в условии апдейта добавится еще одно условие, код сортировки должен быть меньше первой дырки.
1 июл 14, 12:21    [16242892]     Ответить | Цитировать Сообщить модератору
 Re: Нужна помощь в оптимизации скрипта  [new]
vrtlpilot
Member

Откуда:
Сообщений: 29
Выставляю на критику публики то, что родило мое воспаленное сознание спустя восемь часов "творческих" мук.
DECLARE @KodProdukt int, @KodIB int, @KodSort int, @MinKodSort int, @MaxKodSort int

SET @KodProdukt = 18
SET @KodIB = 254
SET @KOdSort = 10000

SET @MinKodSort = 10000
SET @MaxKodSort = 0

DELETE FROM [Tbl_A] WHERE KodProdukt = @KodProdukt AND KodIB=@KodIB

Select @MinKodSort=Min(KodSort)
From Tbl_A
Where (KodSort>=@KodSort) And (KodProdukt=@KodProdukt)

IF (@MinKodSort = @KodSort) and (@KodSort < 10000)
BEGIN

	SELECT @MaxKodSort = Min(s1.KodSort+1) 
	FROM [Tbl_A] as s1
	WHERE 
		(s1.KodSort+1 NOT IN
			(SELECT s2.KodSort
			FROM [Tbl_A] AS [s2] 
			Where s2.KodProdukt = @KodProdukt))
		AND s1.KodProdukt=@KodProdukt
		AND s1.KodSort < 10000
		AND s1.KodSort>=@MinKodSort

	UPDATE [Tbl_A]
    SET [KodSort] = [KodSort] + 1
    WHERE [KodProdukt] = @KodProdukt
      AND [KodSort] BETWEEN @MinKodSort AND @MaxKodSort

END

IF EXISTS (SELECT [KodProdukt], [KodIB] FROM [dbo].[Tbl_A] WHERE [KodProdukt] = @KodProdukt AND [KodIB] = @KodIB) BEGIN
  UPDATE [dbo].[Tbl_A] SET [KodSort] = @KodSort
    WHERE KodProdukt = @KodProdukt and KodIB = @KodIB
END
ELSE
BEGIN
  INSERT INTO [dbo].[Tbl_A] 
  	([KodProdukt], [KodIB], [KodSort])
  VALUES
  	(@KodProdukt, @KodIB, @KodSort)
END
1 июл 14, 18:25    [16245415]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить