2011-09-01 42 views
1

我有一个问题,现在已经困扰了我几天。我有一个表:插入和转换来自SQL表的数据

  • 日期
  • ID
  • STATUS_ID
  • START_TIME
  • END_TIME
  • STATUS_TIME(秒)(他们怎么玲是在一定的地位,以秒为单位)

我想把这个数据放在另一个表中,Status_ID分组为列。这个表有像这样的列:

  • 日期
  • ID
  • 午餐(以秒计)
  • 中断(以秒计)
  • 度假,(秒)等。

因此,Status_ID 2和3可能会分组在假期,Status_ID 1午餐等。

我曾想过在while循环中嵌套一个Case,要遍历每一行插入到其他表中。但是,我无法将自己的状态码中的这些数据插入行中,将它们分组到列中。

+0

您是否使用合并表和一些临时表来分段数据? –

+0

我没有。我现在会研究这一点。谢谢。 – Jessica

回答

2

不需要WHILE循环。

SELECT 
    date, 
    id, 
    SUM(CASE WHEN status_id = 1 THEN status_time ELSE 0 END) AS lunch, 
    SUM(CASE WHEN status_id = 2 THEN status_time ELSE 0 END) AS break, 
    SUM(CASE WHEN status_id = 3 THEN status_time ELSE 0 END) AS vacation 
FROM 
    My_Table 
GROUP BY 
    date, 
    id 

此外,保持在表中status_time是错误的(除非它是一个非持久性,计算列)。您实际上将相同的数据存储在数据库中的两个地方,最终导致不一致。将这些数据按状态类型细分的时间推入另一个表中也是如此。不要创建一个保存数据的新表,在需要时使用查询来获取数据。

+1

迄今为止,这帮助了我。谢谢! – Jessica

0

这种类型的查询(将行中的值转换为列)被命名为数据透视查询(SQL Server)或交叉表(Access)。

有两种类型的枢轴的查询(一般来说):

  1. 使用固定数量的列。
  2. 具有动态数量的列。

SQL Server支持两种类型的但:

  • 数据库引擎(查询语言:T-SQL)支持仅直接枢轴 查询具有固定数量的列(1)和间接(2)
  • 分析服务(查询语言:MDX)直接支持这两种类型(1 & 2)。 另外,您可以使用OPENQUERY/OPENROWSET函数或使用具有四部分名称的链接服务器从T-SQL查询(MDX)Analysis Service数据源。

T-SQL(只)解决方案:

对于第一类(1),从SQL Server 2005中您可以使用PIVOT操作:

SELECT pvt.* 
FROM 
(
SELECT Date, Id, Status_ID, Status_Time 
FROM Table 
) src 
PIVOT (SUM(src.Status_Time) FOR src.Status_ID IN ([1], [2], [3])) pvt 

SELECT pvt.Date, pvt.Id, pvt.[1] AS Lunch, pvt.[2] AS [Break], pvt.[3] Vacation 
FROM 
(
SELECT Date, Id, Status_ID, Status_Time 
FROM Table 
) src 
PIVOT (SUM(src.Status_Time) FOR src.Status_ID IN ([1], [2], [3])) pvt 

对于动态数量的列(2),T-SQL仅提供间接解决方案:动态查询。首先,您必须从Status_ID中找到所有不同的值,然后下一步是构建最终查询:

DECLARE @SQLStatement NVARCHAR(4000) 
      ,@PivotValues NVARCHAR(4000); 
    SET @PivotValues = ''; 

    SELECT @PivotValues = @PivotValues + ',' + QUOTENAME(src.Status_ID) 
    FROM 
    (
      SELECT DISTINCT Status_ID 
      FROM Table 
    ) src; 
    SET @PivotValues = SUBSTRING(@PivotValues,2,4000); 

    SELECT @SQLStatement = 
    'SELECT pvt.* 
    FROM 
    (
    SELECT Date, Id, Status_ID, Status_Time 
    FROM Table 
    ) src 
    PIVOT (SUM(src.Status_Time) FOR src.Status_ID IN ('[email protected]+')) pvt'; 

    EXECUTE sp_executesql @SQLStatement;