Как создать таблицу пар имя-значение в SQL - PullRequest
2 голосов
/ 06 октября 2009

Используя SQL, как мне преобразовать таблицу из одной строки следующим образом ...

Firstname Surname Address1        City   Country
--------- ------- --------------- ------ -------
Bob       Smith   101 High Street London UK

... в таблицу из имя-значение таких пар:

Name      Value
--------- -------
Firstname   Bob
Surname     Smith
Address1    101 High Street
City        London
Country     UK

Этот скрипт создаст исходную таблицу:

create table #OriginalTable (Firstname varchar(10), Surname varchar(10), 
Address1 varchar(50), City varchar(10), Country varchar(10))
insert into #OriginalTable 
select 
'Bob' Firstname, 
'Smith' Surname, 
'101 High Street' Address1, 
'London' City, 
'UK' Country

Мне нужно общее решение, которое не зависит от того, какие имена столбцов всегда совпадают с именами в примере.

EDIT: Я использую SQL Server 2005. Решение, которое мне нужно, - это сценарий SQL для преобразования этих данных в таблицу пар имя-значение

Ответ: Используя ответ, который я принял в качестве ответа, вот что я использовал:

select   
result.Name, 
result.Value    
from   
  (select
    convert(sql_variant,FirstName) AS FirstName,
    convert(sql_variant,Surname) AS Surname,
    convert(sql_variant,Address1) AS Address1,
    convert(sql_variant,City) AS City,
    convert(sql_variant,Country) AS Country
    from #OriginalTable) OriginalTable
  UNPIVOT (Value For Name In (Firstname, Surname, Address1, City, Country)) as result

Ответы [ 5 ]

6 голосов
/ 06 октября 2009

Обычно у вас есть две проблемы - до UNPIVOT, типы данных должны соответствовать. Другая проблема заключается в том, что количество столбцов неизвестно. Вы хотите достичь чего-то вида:

WITH    conformed
      AS ( SELECT   CONVERT(VARCHAR(255), [Firstname]) AS [Firstname],
                    CONVERT(VARCHAR(255), [Surname]) AS [Surname],
                    CONVERT(VARCHAR(255), [Address1]) AS [Address1],
                    CONVERT(VARCHAR(255), [City]) AS [City],
                    CONVERT(VARCHAR(255), [Country]) AS [Country]
           FROM     so1526080
         )
SELECT  ColumnKey,
        ColumnValue
FROM    conformed UNPIVOT ( ColumnValue FOR ColumnKey IN ( [Firstname], [Surname], [Address1], [City], [Country] ) ) AS unpvt

Таким образом, используя динамический SQL PIVOT с использованием метаданных (вам может потребоваться исправить это с помощью TABLE_SCHEMA и т. Д.):

DECLARE @table_name AS SYSNAME
SET @table_name = 'so1526080'
DECLARE @conform_data_type AS VARCHAR(25)
SET @conform_data_type = 'VARCHAR(255)'

DECLARE @column_list AS VARCHAR(MAX)
DECLARE @conform_list AS VARCHAR(MAX)

SELECT  @conform_list = COALESCE(@conform_list + ', ', '') + 'CONVERT('
        + @conform_data_type + ', ' + QUOTENAME(COLUMN_NAME) + ') AS '
        + QUOTENAME(COLUMN_NAME),
        @column_list = COALESCE(@column_list + ', ', '')
        + QUOTENAME(COLUMN_NAME)
FROM    INFORMATION_SCHEMA.COLUMNS
WHERE   TABLE_NAME = @table_name

DECLARE @template AS VARCHAR(MAX)

SET @template = '
WITH    conformed
          AS ( SELECT  {@conform_list}
               FROM     {@table_name}
             )
    SELECT  ColumnKey,
            ColumnValue
    FROM    conformed UNPIVOT ( ColumnValue FOR ColumnKey IN ( {@column_list} ) ) AS unpvt
    '

DECLARE @sql AS VARCHAR(MAX)
SET @sql = REPLACE(REPLACE(REPLACE(@template, '{@conform_list}', @conform_list),
                           '{@column_list}', @column_list), '{@table_name}',
                   @table_name)    

PRINT @sql
EXEC ( @sql
    )
0 голосов
/ 06 октября 2009

Используйте две таблицы. Одна таблица в виде таблицы ключей и основная таблица содержат идентификатор таблицы ключей вместе со значением.

Затем вы можете добавить такие вещи, как client_id или что-то еще, в основную таблицу и установить уникальный ключ для client_id и key_id.

0 голосов
/ 06 октября 2009

Не то чтобы это было полное решение, но идея мозгового штурма, что если вы скрестите информацию с таблицей information_schema.columns?

SELECT column_name, OriginalTable.*
FROM information_schema.columns 
CROSS JOIN OriginalTable
WHERE table_name = 'OriginalTable'
AND /* PRIMARY KEY FILTER HERE*/
0 голосов
/ 06 октября 2009

Часто наиболее эффективно поворачивать приложение, используя код приложения. Поворот не является сильной стороной базы данных.

0 голосов
/ 06 октября 2009

Это похоже на то, что может делать предложение PIVOT в SQL Server с 2005 года (посмотрите на первый пример), но вы не упоминаете, какой механизм базы данных вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...