【问题标题】:Splitting the results into separate columns将结果拆分为单独的列
【发布时间】:2013-08-02 06:54:24
【问题描述】:

我需要一个视图兼容的 SQL 查询来完成以下结果(视图 1)。

Table 1:
--------------
ID |    Folder
--------------
1  |    foo
2  |    bar

Table 2:
-------------------------------------
ID |    Table1_ID | Name    |   Right
-------------------------------------
1  |    1         | fooUser |   W
2  |    2         | barUser |   R

View 1:
-------------------------------
Folder  |   fooUser  |  barUser
-------------------------------
foo     |     W      |
bar     |            |    R

我只能使用自定义函数来做到这一点,但我只能将其用作存储过程。我想将结果绑定到 GridView。 我希望任何人都可以帮助我。

【问题讨论】:

  • 如果您希望在将第三行添加到表 2 时它是动态的(并希望出现新列),您将不会从视图(或任何其他可组合的对象)中获取它进入更大的查询) - 视图中的查询只能是静态查询,并且任何特定的静态查询总是产生具有相同“形状”的结果 - 固定数量的列,这些列的名称和数据类型也是固定的。
  • 我当然需要动态数据。我知道我的尝试是不可能的,因为我没有找到任何可能的解决方案。谢谢你为我解决这个问题。不知道我是否应该创建一个新主题,但无论如何我都会问:实体框架可以为我完成任务吗?还是在运行时创建数据表是最常见的解决方案?

标签: sql sql-server sql-view sql-server-2008r2-express


【解决方案1】:

您可以使用带有 CASE 表达式的聚合函数将数据从行转换为列:

select t1.folder,
  max(case when t2.name = 'fooUser' then [right] else '' end) fooUser,
  max(case when t2.name = 'barUser' then [right] else '' end) barUser
from table1 t1
inner join table2 t2
  on t1.id = t2.Table1_ID
group by t1.folder;

SQL Fiddle with Demo

如果您需要动态解决方案,那么您将需要使用动态 SQL:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Name) 
                    from table2
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT folder, ' + @cols + ' 
            from 
            (
              select t1.folder,
                t2.name, t2.[right]
              from table1 t1
              inner join table2 t2
                on t1.id = t2.Table1_ID
            ) x
            pivot 
            (
                max([right])
                for name in (' + @cols + ')
            ) p '

execute(@query);

SQL Fiddle with Demo

【讨论】:

  • 因为我需要动态数据,所以我也不能使用你的解决方案。但我想知道您的解决方案与@makciook 的解决方案之间的速度差异
  • 问题是我不能使用动态 SQL 作为视图和存储过程作为我的控件的数据源。
  • @Bonzai 如果不在存储过程中使用动态 SQL,则无法动态执行此操作。
  • @Bonzai “我需要动态数据”......“我不能使用动态 SQL”......你是一个行走的矛盾。如果您想要动态列,则需要动态 SQL,或者您需要更改您的要求。
  • 感谢您确认@Damien_The_Unbeliever 的声明。
【解决方案2】:

只是为了好玩,这是一个愚蠢的答案,但它有效 :) 我建议使用 PIVOT 虽然@makciook。

select a.Folder,
       foo.[Right] fooUser,
       bar.[Right] barUser
  from one a
  left join two foo on a.ID = 1 and foo.ID = 1
  left join two bar on a.ID = 2 and bar.ID = 2

【讨论】:

    【解决方案3】:

    只要您想将值转换为列,请使用PIVOT。在这里你需要一个选择:

    SELECT Folder, [fooUser], [baruser]
    FROM (SELECT t.Folder, tt.* FROM one t JOIN two tt ON t.ID = tt.Table1_ID) AS source
    PIVOT
    (
      MAX(Rightt)
      FOR Name IN (fooUser, barUser)
    ) AS PivotTable;
    

    将它应用到CREATE VIEW ... AS,它应该可以工作。

    SQLFiddle

    【讨论】:

    • 感谢您的解决方案,但我忘了说我说的是动态数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 2020-12-14
    • 2018-05-17
    • 2019-11-05
    • 1970-01-01
    相关资源
    最近更新 更多