将空值替换为每个组中以前的非空值



我正在通过自定义SQL查询连接到Tableau 上的Microsoft SQL Server。我有一个包含 3 个字段的表日期时间、标签名称、值,我想将"值"字段中的空值替换为每组 TagName 中的最后一个(根据日期时间值(非空值。

|---------------------|------------------|-----------------|
|     DateTime        |     TagName      |      Value
|---------------------|------------------|-----------------
|  15.04.2019 16:51:30|         A        |       10
|---------------------|------------------|----------------- 
|  15.04.2019 16:52:42|         A        |       NULL
|---------------------|------------------|----------------- 
|  15.04.2019 16:53:14|         A        |       NULL
|---------------------|------------------|----------------- 
|  15.04.2019 17:52:14|         A        |       15
|---------------------|------------------|----------------- 
|  15.04.2019 16:51:30|         B        |       NULL
|---------------------|------------------|----------------- 
|  15.04.2019 16:52:42|         B        |       NULL
|---------------------|------------------|-----------------
|  15.04.2019 16:53:14|         B        |       NULL
|---------------------|------------------|----------------- 
|  15.04.2019 17:52:14|         B        |       15
|---------------------|------------------|-----------------|

新表应如下所示:

|---------------------|------------------|-----------------|
|     DateTime        |     Computer     |      Value
|---------------------|------------------|-----------------
|  15.04.2019 16:51:30|         A        |       10
|---------------------|------------------|----------------- 
|  15.04.2019 16:52:42|         A        |       10
|---------------------|------------------|----------------- 
|  15.04.2019 16:53:14|         A        |       10
|---------------------|------------------|----------------- 
|  15.04.2019 17:52:14|         A        |       15
|---------------------|------------------|----------------- 
|  15.04.2019 16:51:30|         B        |       0
|---------------------|------------------|----------------- 
|  15.04.2019 16:52:42|         B        |       0
|---------------------|------------------|-----------------
|  15.04.2019 16:53:14|         B        |       0
|---------------------|------------------|----------------- 
|  15.04.2019 17:52:14|         B        |       15
|---------------------|------------------|-----------------|

这已经是我尝试过的了,但它在不考虑 TagNames 值的情况下替换了 NULL 值(在此示例中只有一个 TagName(。

SELECT  Computer, DateTime
,       CASE 
        WHEN Value IS NULL 
        THEN                                
       (SELECT TOP 1 Value 
        FROM History 
        WHERE DateTime<T.DateTime 
              AND TagName='RM02EL00CPT81.rEp'
              AND DateTime >='2018-12-31 23:59:00' 
              AND wwRetrievalMode='Delta'
              AND Value IS NOT NULL ORDER BY DateTime DESC
       ) 
        ELSE Value 
        END 
        AS ValueNEW
FROM History T
WHERE  TagName='RM02EL00CPT81.rEp' AND DateTime >='2018-12-31 23:59:00' AND wwRetrievalMode='Delta'

我想通过添加OVER(PARTITION BY TagName)来做几乎相同的事情,但它抛出了一个错误。(这是因为它不适用于SELECT TOP 1

这是一个

"经典"的差距和岛屿问题。您可以使用窗口函数实现此目的,而无需 2 次扫描或三角形连接:

WITH VTE AS(
    SELECT CONVERT(datetime, [DateTime],104) AS [DateTime],
           TagName,
           [Value]
    FROM (VALUES ('15.04.2019 16:51:30','A',10  ),
                 ('15.04.2019 16:52:42','A',NULL),
                 ('15.04.2019 16:53:14','A',NULL),
                 ('15.04.2019 17:52:14','A',15  ),
                 ('15.04.2019 16:51:30','B',NULL),
                 ('15.04.2019 16:52:42','B',NULL),
                 ('15.04.2019 16:53:14','B',NULL),
                 ('15.04.2019 17:52:14','B',15  )) V([DateTime],TagName,[Value])),
Grps AS(
    SELECT [DateTime],
           TagName,
           [Value],
           COUNT(CASE WHEN [Value] IS NOT NULL THEN 1 END) OVER (PARTITION BY TagName ORDER BY [DateTime]
                                                                 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
    FROM VTE)
SELECT DateTime,
       TagName,
       ISNULL(MAX([Value]) OVER (PARTITION BY TagName, Grp),0) AS [Value]
FROM Grps
ORDER BY TagName, [DateTime]

试试这个

;WITH CTE([DateTime],TagName,Valu)
AS
(
SELECT '15.04.2019 16:51:30','A' , 10    UNION ALL
SELECT '15.04.2019 16:52:42','A' , NULL  UNION ALL
SELECT '15.04.2019 16:53:14','A' , NULL  UNION ALL
SELECT '15.04.2019 17:52:14','A' , 15    UNION ALL
SELECT '15.04.2019 16:51:30','B' , NULL  UNION ALL
SELECT '15.04.2019 16:52:42','B' , NULL  UNION ALL
SELECT '15.04.2019 16:53:14','B' , NULL  UNION ALL
SELECT '15.04.2019 17:52:14','B' , 15
)
SELECT [DateTime],TagName As Computer,
        ISNULL(CASE WHEN Valu IS NOT NULL   
            THEN Valu
            ELSE 
                (
                SELECT TOP 1 Valu FROM  
                CTE i
                WHERE i.TagName = o.TagName     
                ) END,0) As Valu
FROM CTE o

结果

DateTime                Computer    Valu
---------------------------------------------
15.04.2019 16:51:30     A           10
15.04.2019 16:52:42     A           10
15.04.2019 16:53:14     A           10
15.04.2019 17:52:14     A           15
15.04.2019 16:51:30     B           0
15.04.2019 16:52:42     B           0
15.04.2019 16:53:14     B           0
15.04.2019 17:52:14     B           15

因此,您正在尝试从 Wonderware Historian 检索数据。也许您不需要任何窗口和替换,因为 Historian 检索引擎应该能够为您提供所需的数据,而无需空值。试试这个:

select DateTime, TagName as Computer, Value
from History
where TagName in ('A', 'B') --put here the tagnames you want to retrieve
and DateTime > '2018-12-31'
AND wwRetrievalMode='Delta'
order by TagName, DateTime

相关内容

  • 没有找到相关文章

最新更新