SQL преобразовывает данные строк в столбец, используя одну таблицу - PullRequest
2 голосов
/ 16 августа 2011

Я пытаюсь преобразовать одну из строк таблицы БД в столбец и использую функцию PIVOT с курсорами, вот Sql:

DECLARE Cur CURSOR FOR
  SELECT DISTINCT CounterId
  FROM AllCounterIds

DECLARE @Temp NVARCHAR(MAX),
  @AllCounterIds NVARCHAR(MAX),
  @CounterIdQuery NVARCHAR(MAX)

SET @AllCounterIds = ''

OPEN Cur
-- Getting all the movies
FETCH NEXT FROM Cur INTO @Temp
WHILE @@FETCH_STATUS = 0
BEGIN
 SET @AllCounterIds = @AllCounterIds + '[' + @Temp + '],'
 FETCH NEXT FROM Cur INTO @Temp
END

CLOSE Cur
DEALLOCATE Cur

SET @AllCounterIds = SUBSTRING(@AllCounterIds, 0, LEN(@AllCounterIds))

SET @CounterIdQuery = 'SELECT DateTime, ' + @AllCounterIds + '
FROM 
(SELECT Type, DateTime, Value, AllCounterIds.CounterId
FROM AllCounterIds
 INNER JOIN AllCounters
  ON AllCounterIds.CounterId = AllCounters.CounterId) S
PIVOT
(
SUM (Value)
FOR CounterId IN
(' + @AllCounterIds + ')) AS pvt'

EXEC sp_executesql @CounterIdQuery

где AllCounterIds - это представление, которое я создал с помощью этого:

GO
CREATE VIEW AllCounterIds AS 
SELECT DISTINCT CounterId FROM AllCounters
GO

Итак, проблема в том, что у меня сейчас в таблице около 27993600 строк, и когда я выполняю SQL, это занимает около 4 минут и около 15 секунд, чтобы дать мне вывод, а в соответствии с требованиями к производительности это плохо ... так что мой вопрос что, в любом случае, где я могу достичь желаемого результата, но получить лучшую производительность?

И просто, чтобы вы знали, что кластерные индексы также определены в таблице ...

1 Ответ

2 голосов
/ 16 августа 2011

Я не уверен, что это на самом деле быстрее для вашего случая, но, возможно, попробуйте что-то вроде этого

declare
    @allcounterids varchar(max),
    @counteridquery varchar(max)
;

select
    @allcounterids = stuff((
    select 
            '],[' + cast([CounterId] as varchar(32))
        from
            allcounterids
        for xml path('')), 1, 2, '') + ']'
;

set @counteridquery = 'select
        s.datetime, pvt.*
    from
        (SELECT Type, DateTime, Value, AllCounterIds.CounterId
            FROM AllCounterIds
            INNER JOIN AllCounters
                ON AllCounterIds.CounterId = AllCounters.CounterId
        ) S
        PIVOT
        (
            SUM (Value)
            FOR CounterId IN
            (' + @AllCounterIds + ')
        ) AS pvt;'
;
execute(@counteridquery);

Использование varchar вместо nvarchar является преднамеренным. Маловероятно, что нужен юникод для списка целых чисел, и это сэкономит некоторую память, а значит, и время.

...