SQL Server 2000: создание и приращение данных из столбца условно без использования CURSOR - PullRequest
3 голосов
/ 30 декабря 2011

:)

Есть ли способ создания индекса и приращения с заданным условием, но без обработки / использования CURSOR

Например:

sql_tables

Условие в моем случае таково: «если текущий цвет (это проверяемый элемент) совпадает с последним: не увеличивается, иначе увеличивается на одну единицу»

Это должно быть в SQL-запросе без ИСПОЛЬЗОВАНИЯ КУРСА и, конечно, хорошее время (работа с ... не менее 10000 строк)

Заранее спасибо.

РЕДАКТИРОВАТЬ: я забылотметить, что столбец NEW_INDEX не существует.Он должен быть создан с помощью запроса.

EDIT2: Есть ли способ, который использует только операторы SELECT / INSERT / UPDATE?(не задано, объявить ...)

Ответы [ 3 ]

2 голосов
/ 30 декабря 2011
declare @ID int, 
        @MaxID int, 
        @NewIndex int, 
        @PrevCol varchar(50)

select @ID = min(ID),
       @MaxID = max(ID),
       @PrevCol = '',
       @NewIndex = 0       
from YourTable       

while @ID <= @MaxID
begin
  select @NewIndex = case when Colour = @PrevCol 
                       then @NewIndex 
                       else @NewIndex + 1 
                     end,
         @PrevCol = Colour
  from YourTable
  where ID = @ID

  update YourTable 
  set NewIndex = @NewIndex
  where ID = @ID

  set @ID = @ID + 1
end

http://data.stackexchange.com/stackoverflow/q/122958/

2 голосов
/ 30 декабря 2011

Предположим, что таблица называется «Цвета» с полями ID, Color и ColorIndex типов int, varchar и int соответственно.Я также предполагаю, что OP означает prev / after, основываясь на упорядочении поля ID в порядке asc.

Вы можете сделать это без курсора и использовать цикл while ... но это определенноне устанавливается на основании:

DECLARE @MyID int
DECLARE @CurrentIndex int
DECLARE @CurrentColor varchar(50)
DECLARE @PreviousColor varchar(50)

SET @CurrentIndex = (SELECT 0)

SET @MyID = (SELECT TOP 1 ID FROM Colors ORDER BY ID ASC)
SET @CurrentColor = (SELECT '')
SET @PreviousColor = (SELECT Color FROM Colors WHERE ID = @MyID)

WHILE (@MyID IS NOT NULL)
 BEGIN
   IF (@CurrentColor <> @PreviousColor)
     BEGIN
        SET @PreviousColor = (SELECT Color FROM Colors WHERE ID = @MyID)
        SET @CurrentIndex = (SELECT @CurrentIndex + 1)
        UPDATE Colors SET ColorIndex = @CurrentIndex WHERE ID = @MyID
     END 
   ELSE
      BEGIN
        UPDATE Colors SET ColorIndex = @CurrentIndex WHERE ID = @MyID
        SET @PreviousColor = (SELECT Color FROM Colors WHERE ID = @MyID)
      END
 SET @MyID = (SELECT TOP 1 ID FROM Colors WHERE ID > @MyID ORDER BY ID ASC)
 SET @CurrentColor = (SELECT Color FROM Colors WHERE ID = @MyID)
 END

Результат после выполнения:

enter image description here

Производительность не была слишком плохой, пока индексируются идентификатор и цвет.Плюс в том, что он немного быстрее обычного старого КУРСОРА и не такой злой.Решение поддерживает SQL 2000, 2005 и 2008 (если вы используете SQL 2000, который не поддерживает CTE).

1 голос
/ 30 декабря 2011
    select
        IDENTITY(int,1,1) as COUNTER
        ,c1.ID
    into
        #temp
    from
        CUSTOMERS c1
        left outer join (
                select
                    c1.ID, max(p.ID) as PRV_ID
                from
                    CUSTOMERS c1, 
                    (
                    select
                        ID
                    from
                        CUSTOMERS
                    ) p
                where
                    c1.ID > p.ID
                group by
                    c1.ID
                    ) k on k.ID = c1.ID
        left outer join CUSTOMERS p on p.ID = k.PRV_ID 
    where        
        ((c1.FAVOURITE_COLOUR < p.FAVOURITE_COLOUR)
         or
        (c1.FAVOURITE_COLOUR > p.FAVOURITE_COLOUR)
         or
         p.FAVOURITE_COLOUR is null)

    update
        CUSTOMERS
    set
        NEW_INDEX = i.COUNTER 
    --select *
    from    
        CUSTOMERS
        inner join (
            select 
                c1.ID, max(t.COUNTER) as COUNTER
            from
                CUSTOMERS c1, 
                (
                select
                    ID
                    ,COUNTER
                from
                    #temp
                ) t
            where
                c1.ID >= t.ID
            group by
                c1.ID
            ) i on i.ID = CUSTOMERS.ID

    drop table #temp

    select * from CUSTOMERS
...