【问题标题】:Show the record in a table as a column in SQL Server在 SQL Server 中将表中的记录显示为列
【发布时间】:2013-06-03 08:58:06
【问题描述】:

我有一个名称为 tbl_Criteria 的表,此处可用的列是 ID 、名称。
样本记录如下

D        Name
1        Lunch
2        Dinner

我有另一个名为 tbl_Feedback 的表,其列如下所示

ID      UserID    Creteria      Ratings
1        129         2            A
2        329         2            B
3        520         1            C

我的需要是我需要将 creteria 列表显示为列,并且我需要给出评级 如下所示

Dinner  Lunch
A       C
B       Null

希望这很清楚。如果不是,请告诉我。

【问题讨论】:

    标签: sql sql-server-2008 pivot


    【解决方案1】:

    当您将数据从行转换为列时,有几种方法可以做到这一点。您可以使用带有 CASE 表达式的聚合函数,或者由于您使用的是 SQL Server,您可以使用 PIVOT 函数。在这两种情况下,您都将使用 group by 应用某种聚合。

    由于您只想显示ratingsname,如果您将聚合函数应用于字符串列,那么在使用GROUP BY 时将返回一行。

    使用带有 CASE 的聚合函数的语法是:

    select 
      max(case when name = 'Dinner' then ratings end) Dinner,
      max(case when name = 'Lunch' then ratings end) Lunch
    from tbl_feedback f
    inner join tbl_criteria c
      on f.creteria = c.d;
    

    SQL Fiddle with Demo。但是如果你运行上面的查询,你只会返回一行:

    | DINNER | LUNCH |
    ------------------
    |      B |     C |
    

    因此,您需要包含一些允许不同行包含在最终结果中的值。由于您使用的是 SQL Server,因此您可以申请 row_number()。如果您包含row_number(),您可以通过creteria 对数据进行分区,类似于以下内容:

    select 
      max(case when name = 'Dinner' then ratings end) Dinner,
      max(case when name = 'Lunch' then ratings end) Lunch
    from
    (
      select f.ratings, c.name, 
        row_number() over(partition by f.creteria order by f.id) rn
      from tbl_feedback f
      inner join tbl_criteria c
        on f.creteria = c.d
    ) d
    group by rn;
    

    SQL Fiddle with Demo。 row_number 生成应用分组依据时所需的唯一值。

    您也可以在使用 PIVOT 功能时使用row_number()

    select dinner, lunch
    from
    (
      select f.ratings, c.name, 
        row_number() over(partition by f.creteria order by f.id) rn
      from tbl_feedback f
      inner join tbl_criteria c
        on f.creteria = c.d
    ) d
    pivot
    (
      max(ratings)
      for name in (dinner, lunch)
    ) piv;
    

    SQL Fiddle with Demo。这些查询的最终结果将是:

    | DINNER |  LUNCH |
    -------------------
    |      A |      C |
    |      B | (null) |
    

    编辑#1:如果您有未知或动态数量的条件名称,那么您将需要使用动态 sql 来生成结果。

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT distinct ',' + QUOTENAME(name) 
                        from tbl_Criteria
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT ' + @cols + ' 
                from 
                 (
                    select f.ratings, c.name, 
                      row_number() over(partition by f.creteria order by f.id) rn
                    from tbl_feedback f
                    inner join tbl_criteria c
                      on f.creteria = c.d
                ) d
                pivot 
                (
                    max(ratings)
                    for name in (' + @cols + ')
                ) p '
    
    execute(@query)
    

    SQL Fiddle with Demo

    【讨论】:

    • 感谢先生的回复。您只是在 select 语句中提到硬编码的“午餐”和“晚餐”。但是我可以在该表 tbl_createria 中插入更多记录。我需要选择并显示我作为列插入到 tbl_creteria 中的记录。希望这是清楚的先生。如果不是,请告诉我。
    • @user2003780 查看我的编辑,如果值未知,则必须使用动态 sql 获取结果。
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多