SQL Server PIVOT для таблицы ключ-значение - PullRequest
9 голосов
/ 29 декабря 2010

У меня есть таблица, атрибуты которой основаны на значении ключа.Пример:

CREATE TABLE ObjectAttributes
(
  int objectId, key nvarchar(64), value nvarchar(512)
)

Когда я выбираю из этого, я получаю:

objectId  key      value
----------------------------
1         Key 1    Value 1
1         Key 2    Value 2

Мне было интересно, смогу ли я использовать синтаксис PIVOT для преобразования этого в:

objectId  Key 1     Key 2
---------------------------
1         Value 1   Value 2

Я знаю, что все мои таблицы будут иметь одинаковые ключи.(К сожалению, я не могу легко изменить структуру таблицы. Это то, что заставляет меня пытаться использовать PIVOTS).

Большая проблема здесь заключается в том, что для сводных данных требуется использовать функцию агрегирования.Есть ли способ предотвратить это?Я совершенно не прав, пытаясь это сделать?Или есть лучшее решение?

Ответы [ 3 ]

10 голосов
/ 29 декабря 2010

Сводка не будет быстрее, чем повторное самостоятельное соединение для фиксированного вывода столбца.

SELECT
   T1.objectID, T1.Value AS Key1, T2.Value AS Key2
FROM
   ObjectAttributes T1
   JOIN
   ObjectAttributes T2 ON T1.objectID = T2.objectID
WHERE
   T1.key = 'Key 1'
   AND
   T2.key = 'Key 2'

Если вы хотите использовать PIVOT, просто используйте MAX. Поскольку у вас есть одна строка на объект / ключ, это в любом случае тривиально и соответствует требованиям PIVOT.

Если вы хотите PIVOT неизвестное количество строк в столбцах, то это динамический SQL (согласно решениям SQL Server 2000) или это делается в коде клиента.

Если бы у каждого объекта было фиксированное количество атрибутов, я бы рассмотрел наличие второй таблицы с реальными столбцами, поддерживаемыми триггером. Коряво, но облегчает чтение

6 голосов
/ 29 декабря 2010

Нет, вы не можете избежать совокупности. SQL Server необходимо каким-то образом объединить множество возможных строк в одно значение. У вас есть одно значение, но функциональность PIVOT создана с учетом множества строк.

SELECT objectId, [Key 1], [Key 2]
FROM
(SELECT objectId, [key], value FROM ObjectAttributes) AS source
PIVOT
(
 MIN(value)
 FOR [key] IN ([Key 1], [Key 2])
) as pvt
0 голосов
/ 13 июня 2019

Я добавляю этот ответ, поскольку эта тема является одной из первых, появившихся в Google по этому вопросу.

Самое простое решение, которое я нашел, это использовать комбинацию max с case, как это:

-- Pivot the data with a handwritten T-SQL statement.
-- Make sure you have an index defined on the grouping column.
SELECT
    RecordID,
    -- Spreading and aggregation phase
    MAX(CASE WHEN Element = 'FirstName' THEN Value END) AS 'FirstName',
    MAX(CASE WHEN Element = 'LastName' THEN Value END) AS 'LastName',
    MAX(CASE WHEN Element = 'City' THEN Value END) AS 'City',
    MAX(CASE WHEN Element = 'Country' THEN Value END) AS 'Country'
FROM EAVTable
GROUP BY RecordID -- Grouping phase

Ссылка: https://www.sqlpassion.at/archive/2014/08/25/the-dangerous-beauty-of-the-pivot-operator-in-sql-server/

Это решение также работает практически для всех, и вам не нужно много объединяться, если вам нужно повернуть много столбцов

...