SQL查询的建议,行值为列

时间:2014-01-31 18:58:40

标签: c# sql sql-server pivot pivot-table

将具有不同区域值的结果集作为以下基本选择查询中的列返回的最佳方法是什么?

SELECT weight, base_rate, zone 
FROM Rates 
WHERE modeId = 984 

这是表格:

Rates表:

    id int
    modeId int
    base_rate decimal
    zone varchar
    weight decimal

我尝试创建一个数据透视查询来完成此任务,但到目前为止都没有成功。有任何想法吗?我应该只是在C#代码中操作结果吗?结果将被放入gridview。

这就是我希望结果集看起来像

weight zone1 zone2 zone3 zone4
5       5.50 5.65  5.75  6.00
10      5.55 6.00  7.00  8.00
15      7.50 8.00  9.00  10.00

这是我尝试创建数据透视查询失败。

select *
from
(
  SELECT weight, base_rate, zone FROM Rates where modeId=984 
) as d
pivot
(
  max(weight)
  for zone in (select distinct zone from d)
) piv;

2 个答案:

答案 0 :(得分:1)

SQL Server不允许使用SELECT语句来获取PIVOT的列列表。必须在运行时知道列名称。

如果您的值有限,则需要对查询进行硬编码:

select weight, Zone1, Zone2, Zone3, Zone4
from
(
  SELECT weight, base_rate, zone 
  FROM Rates where modeId=984 
) as d
pivot
(
  max(base_rate)
  for zone in (Zone1, Zone2, Zone3, Zone4)
) piv;

但是,如果您将拥有未知数量的值,那么您需要查看使用动态SQL。这将创建一个sql字符串,然后在运行时执行。语法类似于:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(zone) 
                    FROM Rates 
                    where modeId=984 
                    group by zone
                    order by zone
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT weight,' + @cols + ' 
            from 
            (
                SELECT weight, base_rate, zone 
                FROM Rates where modeId=984 
            ) x
            pivot 
            (
                max(base_rate)
                for zone in (' + @cols + ')
            ) p '

execute sp_executesql @query;

答案 1 :(得分:1)

尝试动态查询,如下所示。

declare @pivcols as varchar(200);
select @pivcols = stuff((select distinct '],[' + zone
from Rates order by '],[' + zone
for xml path('')
), 1, 2, '') + ']';


declare @pivquery varchar(500)   
set @pivquery = 'Select '+   
@pivcols +' 
from   
(select weight, base_rate, zone from rates where modeId=984
) as d
PIVOT
(
max(weight)
for zone in ( '+ @pivcols +' )
) AS pvt '


EXECUTE(@pivquery)