【问题标题】:How to pivot data without aggregations and with variable amount of columns?如何在没有聚合和可变列数的情况下对数据进行透视?
【发布时间】:2023-01-07 03:39:56
【问题描述】:

我有下表:

machineId periodId errorId
AGR0.37576 13 ERR561
AGR0.37576 14 ERR561
AGR0.37576 14 ERR458
AGR0.37576 15 ERR561
AGR0.37576 15 ERR458
AGR0.37576 16 ERR458
AGR0.37576 16 ERR561
AGR0.37576 17 ERR561
AGR0.37576 17 ERR458
AGR0.37576 18 ERR458
AGR0.37576 18 ERR561
AGR0.37576 19 ERR561
AGR0.37576 20 ERR561
  • 机器ID" 是一个唯一标识符,用于标识我们手头的机器 [农业总收入(农业)0(拖拉机).37576(机器本身的SN)]

  • 周期Id" 是该期间的唯一标识符:例如13(2021-12-31),14(2022-01-01)等

  • 错误编号" 是机器在那段时间出现的错误的唯一标识符。例如ERR561- 过热,ERR457- 冷却液液位很低,ERR458- 冷却液液位非常低 每个周期可能出现一个或多个错误。如果错误多于一个,则插入具有相同周期的新记录和新的错误代码。

我想像这样旋转并呈现表格:

machineId periodId ERROR1 ERROR2 ERROR3 ERROR4
AGR7.00012 9 ERR221 MIS061 ERG737 SER003
AGR0.37576 13 ERR561 NULL NULL NULL
ROAD.88887 13 ERR561 NULL NULL NULL
AGR0.37576 14 ERR845 ERR561 ERR737 NULL

我有两个问题:

1.到目前为止,我能找到的所有内容都或多或少地解释了如何将销售数据转向某个时期(Qs、HYs 等)。正如您所看到的唯一一列,我可以汇总的是周期Id,这是没有意义的。

2.每个时间段的错误数量各不相同,我可以在给定时间段内每台机器没有错误,而在另一个时间段内可以有 100 个错误。 任何想法如何使用 SQL 实现这一点?

样本数据:

DROP TABLE IF EXISTS #sampleData
CREATE TABLE #sampleData ( [machineId] varchar(18), [periodId] int, [errorId] varchar(13) )

INSERT INTO #sampleData ([machineId], [periodId], [errorId])
VALUES
( 'AGR0.37576', 13, 'ERR561' ),
( 'AGR0.37576', 14, 'ERR561' ),
( 'AGR0.37576', 14, 'ERR458' ),
( 'AGR0.37576', 14, 'ERR737' ),
( 'AGR0.37576', 15, 'ERR561' ),
( 'AGR0.37576', 15, 'ERR458' ),
( 'AGR0.37576', 16, 'ERR458' ),
( 'AGR0.37576', 16, 'ERR561' ),
( 'AGR0.37576', 17, 'ERR561' ),
( 'AGR0.37576', 17, 'ERR458' ),
( 'AGR0.37576', 18, 'ERR458' ),
( 'AGR0.37576', 18, 'ERR561' ),
( 'AGR0.37576', 19, 'ERR561' ),
( 'AGR0.37576', 20, 'ERR561' ),
( 'AGR0.37576', 21, 'ERR561' ),
( 'AGR0.37576', 22, 'ERR561' ),
( 'AGR0.37576', 29, 'ERR561' ),
( 'AGR0.37576', 30, 'ERR561' ),
( 'AGR0.37576', 96, 'ERR561' ),
( 'AGR0.37576', 97, 'ERR561' ),
( 'AGR0.37576', 111, 'ERR561' ),
( 'AGR0.37576', 112, 'ERR561' ),
( 'AGR0.37576', 113, 'ERR561' ),
( 'AGR7.00012', 9, 'ERR221' ),
( 'AGR7.00012', 9, 'MIS061' ),
( 'AGR7.00012', 9, 'ERG737' ),
( 'AGR7.00012', 9, 'SER003' ),
( 'ROAD.88887', 13, 'ERR561' )

【问题讨论】:

  • 你能编辑“预期输出”吗?
  • SQL 透视函数只能使用一组已定义的值。在您的情况下,您似乎想按机器/期间显示错误。这将需要使用外部应用的自定义查询。当相同的 errorId 在同一时期/机器上发生时,输出会附加什么?
  • 使枢轴逻辑更加清晰。
  • 如果您不知道所有可能的列,则需要 dynamic PIVOT

标签: sql-server tsql


【解决方案1】:

我在 SampleData 表中添加了两列:

  1. Id:我不知道你表中的顺序
  2. RowNum:要知道我必须向临时表添加多少列。

    通常,您可以玩这个脚本并对其进行改进。

    DROP TABLE IF EXISTS #sampleData
    CREATE TABLE #sampleData ( [machineId] varchar(18), [periodId] int, [errorId] varchar(13), Id INT IDENTITY, RowNum INT)
    
    INSERT INTO #sampleData ([machineId], [periodId], [errorId])
    VALUES
    ( 'AGR0.37576', 13, 'ERR561' ),
    ( 'AGR0.37576', 14, 'ERR561' ),
    ( 'AGR0.37576', 14, 'ERR458' ),
    ( 'AGR0.37576', 14, 'ERR737' ),
    ( 'AGR0.37576', 15, 'ERR561' ),
    ( 'AGR0.37576', 15, 'ERR458' ),
    ( 'AGR0.37576', 16, 'ERR458' ),
    ( 'AGR0.37576', 16, 'ERR561' ),
    ( 'AGR0.37576', 17, 'ERR561' ),
    ( 'AGR0.37576', 17, 'ERR458' ),
    ( 'AGR0.37576', 18, 'ERR458' ),
    ( 'AGR0.37576', 18, 'ERR561' ),
    ( 'AGR0.37576', 19, 'ERR561' ),
    ( 'AGR0.37576', 20, 'ERR561' ),
    ( 'AGR0.37576', 21, 'ERR561' ),
    ( 'AGR0.37576', 22, 'ERR561' ),
    ( 'AGR0.37576', 29, 'ERR561' ),
    ( 'AGR0.37576', 30, 'ERR561' ),
    ( 'AGR0.37576', 96, 'ERR561' ),
    ( 'AGR0.37576', 97, 'ERR561' ),
    ( 'AGR0.37576', 111, 'ERR561' ),
    ( 'AGR0.37576', 112, 'ERR561' ),
    ( 'AGR0.37576', 113, 'ERR561' ),
    ( 'AGR7.00012', 9, 'ERR221' ),
    ( 'AGR7.00012', 9, 'MIS061' ),
    ( 'AGR7.00012', 9, 'ERG737' ),
    ( 'AGR7.00012', 9, 'SER003' ),
    ( 'ROAD.88887', 13, 'ERR561' )
    
    
     ;WITH T1 AS (
                    SELECT [machineId], [periodId], [errorId], RowNum,
                                    ROW_NUMBER() OVER (PARTITION BY [machineId], [periodId] ORDER BY Id) AS RowNumber
                    FROM #sampleData
                                        )
      UPDATE T1 SET RowNum = RowNumber
    
    
     CREATE TABLE #Temp (machineId VARCHAR(18), periodId INT)
    
     
     INSERT INTO #Temp (machineId, periodId)
     SELECT machineId, periodId
     FROM #sampleData
     GROUP BY machineId, periodId
    
    
    
     DECLARE @UpdateStatment AS NVARCHAR(MAX) = ''
     DECLARE @SQLString AS NVARCHAR(MAX) = ''
    
     SELECT @SQLString = @SQLString + ' ALTER TABLE #Temp ADD ERROR' + CAST(S1.RowNum AS NVARCHAR) + '  VARCHAR(13);', 
            @UpdateStatment = @UpdateStatment + 
            'UPDATE T SET ERROR' + CAST(S1.RowNum AS NVARCHAR) + '=  S.ErrorId 
            FROM #Temp T 
                    INNER JOIN #SampleData S ON T.machineId = S.machineId AND T.periodId = S.periodId WHERE S.RowNum = ' + CAST(S1.RowNum AS NVARCHAR) + '; '
     FROM #SampleData S1 INNER JOIN 
               (SELECT [machineId], [periodId] 
                FROM #SampleData 
                GROUP BY [machineId], [periodId] 
                HAVING MAX(RowNum) >= ALL (SELECT RowNum FROM #SampleData) ) AS S2 ON S1.[machineId] = S2.[machineId] AND S1.[periodId]  = S2.[periodId] 
     ORDER BY S1.RowNum
    
     SELECT @SQLString
     SELECT @UpdateStatment
    
     EXEC SP_executesql @SQLString
     EXEC SP_executesql @UpdateStatment
     
     SELECT * FROM #Temp
    
    --DROP TABLE #Temp
    --DROP TABLE #SampleData
    
    
       
    
    
    
    

【讨论】:

    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    相关资源
    最近更新 更多