【问题标题】:advice for SQL query with row values as columns以行值作为列的 SQL 查询建议
【发布时间】:2023-03-25 20:55:01
【问题描述】:

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

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

这是表格:

Rates表:

    id int
    modeId int
    base_rate decimal
    zone varchar
    weight decimal

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

这就是我希望结果集的样子

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;

【问题讨论】:

  • 如果你有固定数量的区域,你可以将表格加入到自身中,每个区域加入一个......有点混乱,但它应该可以工作。
  • 感谢您的评论,我应该提到没有固定数量的区域。
  • 您应该在 C# 中处理这个枢轴。当您没有预先确定的输出格式时,SQL 确实是错误的工具。

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


【解决方案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;

【讨论】:

    【解决方案2】:

    尝试如下动态查询。

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 2012-08-11
      相关资源
      最近更新 更多