从SQL表插入和转换数据

时间:2011-09-01 14:12:57

标签: sql sql-server sql-server-2005

我有一个问题一直困扰着我几天。我有一张桌子:

  • 日期
  • ID
  • STATUS_ID
  • START_TIME
  • END_TIME
  • Status_Time(秒)(他们如何处于特定状态,以秒为单位)

我想将此数据放在另一个表中,该表将Status_ID分组为列。此表包含如下列:

  • 日期
  • ID
  • 午餐(以秒为单位)
  • 休息(以秒为单位)
  • 度假,(以秒为单位)等。

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

我想过在一个while循环中嵌套一个Case,遍历每一行插入到我的另一个表中。但是,我无法将这些数据从行中的Status_ID插入到现在按其分组的列中。

2 个答案:

答案 0 :(得分: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 :(得分:0)

这种类型的查询(将值从行转换为列)被命名为pivot query(SQL Server)或crosstab(Access)。

有两种类型的数据透视查询(一般来说):

  1. 使用固定数量的列。
  2. 使用动态列数。
  3. SQL Server支持这两种类型,但是:

    • 数据库引擎(查询语言:T-SQL)仅支持pivot 具有固定数量的列(1)和间接(2)
    • 的查询
    • Analysis Services(查询语言: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 ('+@PivotValues+') ) pvt';
    
        EXECUTE sp_executesql @SQLStatement;