SQL选择列名作为值

时间:2009-08-09 23:17:41

标签: sql views

我有一个包含列名的数据表:

period, Truck, Car, Boat

如果列包含数值,而period列是1到48的标识列,那么有48行。

我想将这个表格按到一个格式,我有一个名称列和一个值列以及句号列,例如。

period, NameOfVehicle, Value

我想创建一个orignal表的视图来做到这一点?如何选择列名并将它们以及该列中的正确值放入NameOfVehicle和Value列?

2 个答案:

答案 0 :(得分:10)

如果您有固定的列,您可以随时执行此操作:

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语句。

答案 1 :(得分:3)

虽然cletus的查询是正确的,但值得指出的是,您可以在SQL Server 2005及更高版本中使用关键字UNPIVOT来执行几乎相同的操作:

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

UNPIVOT和cletus的解决方案之间的区别在于UNPIVOT不包含[value] IS 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;

根据您在unpivoting后保留的列,这可能是另一个选项(此解决方案将保留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;