KnigaRead.com/

W Cat - Справка по SQL

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн W Cat, "Справка по SQL" бесплатно, без регистрации.
Назад 1 ... 10 11 12 13 14 Вперед
Перейти на страницу:

SELECT col

FROM

(SELECT col1, col2

FROM T) p

UNPIVOT

(col FOR xxx IN

(col1, col2)

)AS unpvt


Значения из столбцов col1 и col2 собираются в одном столбце col вспомогательной таблицы unpvt. Однако есть одна особенность в использовании операторов PIVOT и UNPIVOT - они не учитывают NULL-значения. Результат последнего запроса будет таким:



col

1

1

1

3

2


Это препятствие на пути к решению нашей задачи можно преодолеть, если заменить NULL-значение на входе оператора UNPIVOT псевдозначением, т.е. значением, которого заведомо не может быть в исходных данных, а потом выполнить обратное преобразование:



SELECT NULLIF(col,777)

FROM

(SELECT COALESCE(col1,777) col1, COALESCE(col2,777) col2

FROM T) p

UNPIVOT

(col FOR xxx IN

(col1, col2)

)AS unpvt


Здесь COALESCE(colx,777) заменяет NULL-значения в столбце colx на 777, а функция NULLIF(col,777) выполняет обратное преобразование.

Последнее решение дает нам требуемый результат, однако содержит один изъян - значение 777 может рано или поздно появиться в данных, что будет приводить к неверным результатам. Чтобы устранить этот огрех, можно использовать значение другого типа, которого заведомо не может присутствовать в целочисленном столбце, например, символ 'x'. Естественно, чтобы применить этот подход, для совместимости типов целочисленный тип столбцов следует конвертировать к символьному типу, выполнив при необходимости обратное преобразование конечного результата:



SELECT CAST(NULLIF(col,'x') AS INT)

FROM

(SELECT COALESCE(CAST(col1 AS VARCHAR),'x') col1,

COALESCE(CAST(col2 AS VARCHAR),'x') col2

FROM T) p

UNPIVOT

(col FOR xxx IN

(col1, col2)

)AS unpvt


Несколько слов об эффективности представленных решений. Согласно плану выполнения запроса, основные затраты обусловлены чтением данных (операция сканирования таблицы - Table scan). Для двух первых решений сканирование выполняется дважды, в то время как для последнего (UNPIVOT) - один раз, чем и обусловлено его двойное преимущество в производительности.



DROP TABLE T



Комментарии


Н.Петров (aka sql chuvak) 28-08-2008

Есть еще один вариант, который я использую:



SELECT

CASE a WHEN 1 THEN col1 ELSE col2 END col

FROM T, (SELECT 1 a UNION ALL SELECT 2) B


Декартово произведение таблицы T с выборкой из 2-х строк дает "удвоение" (каждая строка таблицы повторяется 2 раза - для а=1 и а=2). Для первого случая берем значение из col1, а для второго - из col2.

Тут, конечно, есть и union, и join, но, по-моему, в данном вопросе интересует именно единственное сканирование таблицы.


Назад 1 ... 10 11 12 13 14 Вперед
Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*