【问题标题】:Table join and sorting表连接和排序
【发布时间】:2018-01-10 16:13:36
【问题描述】:

我有一个 SQL 表,用于存储从自动化流程记录的流程数据。该表存储变量名称、记录值、时间戳。该表如下所示:

VariableName | VariableValue | Timestamp
------------------------------------------
   Tag_1     |       1       |   Time_1  
   Tag_1     |       5       |   Time_2  
   Tag_1     |       4       |   Time_5  
   Tag_1     |       8       |   Time_7   
   Tag_2     |       3       |   Time_1  
   Tag_2     |       4       |   Time_3  
   Tag_2     |       5       |   Time_6  
   Tag_2     |       7       |   Time_7  
    ...

变量的值在“更改时”记录,因此它们以不同的时间戳出现在表中。

为了能够导出数据并将其用于进一步处理,我们需要对表格进行排序并以不同的形式表示它,即:

Timestamp | Tag_1 | Tag_2
--------------------------
  Time_1  |   1   |   3  
  Time_2  |   5   |   -  
  Time_3  |   -   |   4  
  Time_5  |   4   |   -  
  Time_6  |   -   |   5  
  Time_7  |   8   |   7    

如您所见,表中存在一些表示变量值的“盲点”,这对应于这样一个事实,即此时标签没有记录任何值,即标签值没有变化相对于先前记录的值。

如何使用 SQL 实现这一点?我很可能需要一个具有上述结构的新表。但是,它需要动态创建,因为列数取决于记录的变量数(Tag_1、Tag_2 等)。

创建表和查询数据库不是问题,因为我为此使用了 VB 脚本。但是,我不知道如何制定查询(连接???)以实现该结构...

【问题讨论】:

  • 您好。您是否看过或熟悉数据透视表。这应该给你你想要的。查找 SQL PIVOT。

标签: sql sql-server sorting join


【解决方案1】:

你可以使用这个pivot查询:

SELECT TimeStamp, Tag_1, Tag_2
FROM   mytable
PIVOT  (
         MIN(VariableValue)
         FOR VariableName IN ([Tag_1], [Tag_2])
       ) AS PivotTable;

看到它在rextester.com 上运行。输出:

TimeStamp | Tag_1 | Tag_2
----------+-------+-------
  Time_1  |   1   |   3
  Time_2  |   5   | (null)
  Time_3  |(null) |   4
  Time_5  |   4   | (null)
  Time_6  |(null) |   5
  Time_7  |   8   |   7

您不能直接使用动态列列表执行此操作,但在编程环境中(或在带有execute 的 TSQL 中)您可以动态构建此查询。

【讨论】:

  • Sub-select 在这种情况下不需要。可以是..from mytable PIVOT (MIN(VariableValue)..,应该是动态OP提到的Tag_1, Tag_2, etc.
  • 已更新,@Pரதீப்。谢谢!
【解决方案2】:

使用dynamic sqlpivot

首先计算列名的@Columns 变量。

LogTable 用于获取标签名称。但是,如果您有一个包含已知标签的参考表,那么基于该参考表可能会更好。由于日志表往往会变大。

DECLARE @Columns VARCHAR(max);
DECLARE @SQL VARCHAR(max);

SELECT @Columns = concat(@Columns+', ',QUOTENAME(VariableName)) FROM LogTable GROUP BY VariableName;

SET @SQL = 'SELECT * 
FROM (SELECT VariableName, VariableValue, [Timestamp] FROM LogTable) q
PIVOT (MAX(VariableValue) FOR VariableName IN ('+ @Columns +')) p';

EXEC (@SQL);

【讨论】:

  • 很好的解决方案!最后一行可以是EXEC (@SQL);
  • @trincot 是的,改回来了。
【解决方案3】:

结果表示不正确。

这可能有效。我注意到标签可能不一定只是 Tag_1、Tag_2,在这种情况下,需要更动态的方法。

  SELECT 
[TimeStamp], ISNULL(Max(Tag_1),'-') as Tag_1,  ISNULL(Max(Tag_2),'-') as Tag_2
FROM
(SELECT * FROM dbo.Table_3) as ST
PIVOT
(
MAX(VariableValue)
FOR VariableName in ([Tag_1], [Tag_2])
) AS PT
 Group By [TimeStamp]

结果的正确表示

【讨论】:

  • Group By 不会有任何影响
  • 确实可以,因为请求的输出是按时间戳分组的?否则,TimeStamp 将根据我的屏幕截图重复(不分组)但请随时纠正我的解决方案。我们都在学习。
  • 最后一个结果表好像和我想要实现的一致。正如所指出的,我将处理的数据将是日志数据,因此表可能会很大。我希望该解决方案允许我使用任意变量名。即使我预先知道变量名称是什么,它们也可能根本不会出现在日志表中,因为例如标签的值没有改变。
  • ... 还有一条评论:动态执行查询会更好吗,即通过一个脚本来实现例如 for 循环,还是上面的查询可以完成这项工作?
  • @SQLAndOtherStuffGuy,时间戳通过使用 pivot 语法自动分组。看到它在rextester.com/DIZUI50497 上运行。如果您的环境不是这种情况,则说明有问题(数据、引擎类型或其他问题)。
猜你喜欢
  • 2012-03-10
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 2021-10-22
  • 2017-02-07
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多