如何进行列数变化的交叉表? (ADO SQL Server)

时间:2015-09-25 22:09:26

标签: sql sql-server ado

我试图根据数据编写一个具有可变列数的查询,但我从未做过这样的事情。

我们正在运行ADO并希望有一个查询(可能带有子查询)但没有其他编码或GO语句,存储过程等。

我们计划在可编辑的网格中使用此查询的结果。

以下是我们的数据示例。我们有一份员工清单和一份项目清单。请注意,这不是"总结"交叉表。每个单元只有一个源编号。

我们希望查询结果为每个项目都有一列。此列中的单元格将包含该项目中该员工的小时数。

如果我们添加项目,我们希望在查询结果中显示另一列。

编辑:由于我们在代码中编写查询并提交它,我们可以动态生成查询。我们不需要动态生成代码。例如,在下面的数据中,我们将能够阅读(使用我们的母语)Project表,并知道我们有3个项目以及它们的名称。我们可以在阅读中看到的Pivot中使用它们,但只是不确定如何......

Crosstab source and results

2 个答案:

答案 0 :(得分:3)

这样的事情:http://sqlfiddle.com/#!6/2ded1/6

declare @pivotquery as nvarchar(max)
declare @columnname as nvarchar(max)
select @columnname= isnull(@columnname + ',','') 
      + quotename(name)
from (select name from project) as t2
set @pivotquery = 
     N'with t1 as (
         select ph.employee, e.name as empname, p.name, ph.hours
         from project_hours ph
         inner join project p
         on p.id = ph.project
         inner join employees e
         on e.id = ph.employee
       )
       select *
       from t1
       pivot(sum(hours) for name in (' + @columnname + ')) as pivot_table'
exec sp_executesql @pivotquery

在此处提供了重要帮助和进一步说明:http://sqlhints.com/2014/03/18/dynamic-pivot-in-sql-server/

编辑:当我再次阅读您的问题时,我注意到您在代码中构建了查询,在这种情况下,您可能不需要上面的实用程序,但是您可以在其中构建{程序中的{1}}子句,如下所示:http://sqlfiddle.com/#!6/2ded1/12

for name in

答案 1 :(得分:1)

对于未来的读者,这里是一个使用两个嵌套派生表子查询的通用ANSI语法SQL查询。

此查询应该符合大多数RDMS(SQL Server,MySQL,SQLite,Oracle,PostgreSQL,DB2),因为它不使用CTE窗口函数(WITH)或数据库特定的函数,如SQL Server' s Pivot()

SELECT [Key], [Employee Name], [Age],
       Max(FF) As [First Floor],
       Max(BSMT) As [Basement],
       Max(PRKLotA) As [Parking Lot A]    
FROM (
   SELECT dT.Key,
          dT.[Employee Name],
          dT.[Age],
          CASE WHEN dT.Project = 'First Floor' THEN dT.Hours END As FF,
          CASE WHEN dT.Project = 'Basement' THEN dT.Hours END As BSMT,
          CASE WHEN dT.Project = 'Parking Lot A' THEN dT.Hours END As PRKLotA
   FROM (
          SELECT [Employees].Key, 
                 [Employees.[Employee Name], 
                 Employees.Age, Projects.Project, 
                 [Project Hours].Hours
          FROM [Project Hours] 
          INNER JOIN Employees ON [Project Hours].[Employees FK] = Employees.Key 
          INNER JOIN Projects ON [Project Hours].[Projects FK] = Projects.Key
   ) AS dT
) As dT2    
GROUP BY [Key], [Employee Name], [Age]

输出:

Key Employee Name    Age    First Floor     Basement    Parking Lot A
1            Tim     40           1000          3000    
2           John      5           2000          4000             5000