SQL Выбор имен столбцов в качестве значений - PullRequest
6 голосов
/ 10 августа 2009

У меня есть таблица данных с именами столбцов:

period, Truck, Car, Boat

Если столбцы содержат числовые значения, а столбец периода - это столбец идентификаторов, имеющий от 1 до 48, то есть 48 строк.

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

period, NameOfVehicle, Value

Я хочу создать представление таблицы orignal для этого? Как выбрать имена столбцов и поместить их и правильное значение из этого столбца в столбцы NameOfVehicle и Value?

Ответы [ 2 ]

10 голосов
/ 10 августа 2009

Если у вас есть фиксированные столбцы, вы всегда можете сделать это:

SELECT period, 'Truck' AS NameOfVehicle, Truck AS Value FROM vehicle
UNION ALL
SELECT period, 'Car', Car FROM vehicle
UNION ALL
SELECT period, 'Boat', Boat FROM vehicle

Если столбцы являются динамическими или неизвестными, то это будет немного сложнее, и для запроса схемы и динамического оператора SQL будет использоваться специфическая функциональность поставщика.

3 голосов
/ 10 августа 2009

Несмотря на то, что запрос cletus является правильным, стоит указать, что вы можете использовать ключевое слово UNPIVOT в SQL Server 2005 и более поздних версиях, чтобы сделать почти то же самое:

  select
    period, nameOfVehicle, value
  from T unpivot (
    value for nameOfVehicle in ([Car],[Truck],[Boat])
  ) as U;

Разница между UNPIVOT и решением cletus заключается в том, что UNPIVOT не будет включать строки, для которых [значение] равно NULL. Если вам нужны значения NULL, вам нужно быть немного хитрым и использовать значение, которое никогда не встречается в таблице (здесь я использую пустую строку):

with X(period,Car,Truck,Boat) as (
  select period,coalesce(Car,''),coalesce(Truck,''),coalesce(Boat,'')
  from T
)
  select
    period, nameOfVehicle, case when value = '' then null else value end as value
  from X unpivot (
    value for nameOfVehicle in ([Car],[Truck],[Boat])
  ) as U;

В зависимости от столбцов, которые вы сохраните после отмены поворота, это может быть другой вариант (это решение сохранит значения NULL):

select
  period,
  nameOfVehicle,
  max(case nameOfVehicle 
      when 'Truck' then Truck
      when 'Car' then Car
      when 'Boat' then Boat end) as value
  from T cross join (
  values ('Truck'),('Car'),('Boat')
) as Columns(nameOfVehicle)
group by period, nameOfVehicle;
...