繁体   English   中英

来自不同 Historian 表的动态 SQL 查询

[英]Dynamic SQL query from different Historian tables

我在 SQL 服务器中有一个历史系统,它将某些标签值保存在一个表中。

每个月,系统都会根据下表为这些历史数据创建一个表(分区表)。

例如,此表为 2021 年 2 月 ( [ sqlt_data_1_2021_02 ] ):

在此处输入图像描述

还有另一个表拥有分区表的名称以及每个历史表的开始和结束日期:

在此处输入图像描述

我需要根据开始/结束日期获取 [sqlt_data_x_x_x] 中历史值的数据。 例如: start Date: 10th of Dec 2020 EndDate: 10th of Feb2021

这意味着查询应该首先查看所需的分区表,在这种情况下。 [ sqlt_data_1_2021_02], [ sqlt_data_1_2021_01], [ sqlt_data_1_2020_12]

然后查询将从这三个表中检索日期,并从UNION ALL中检索结果。

我怎样才能动态地做到这一点,因为开始和结束日期是可变的?

我添加了有关要求的更多说明

--第一次查询

select  id from sqlth_te where tagpath like '%tagName%' --tagname is Param for SP

 --Result will be ID=153

第二次查询 end_time 和 Start_time 作为 SP 中的参数

SELECT  pname from sqlth_partitions where end_time >=1611489115070 and sqlth_partitions.start_time <= 1612127027358
--result [sqlt_data_1_2021_01] ,[sqlt_data_1_2021_02]

第三个查询,使用上面查询的结果,它给出了表名

select floatvalue,t_stamp from sqlt_data_1_2021_01  where tagid='153' and t_stamp >=1611489115070--StartDate
union all
select floatvalue,t_stamp from sqlt_data_1_2021_02  where tagid='153'and t_stamp<=1612127027358--EndDate

Sp 所需参数应为 [ EXEC SPname 'tagname',end_time,Start_time ]

一种选择是创建一个获取所有表的动态查询。 但它可能容易出错且难以调试。

相反,我认为您最好的选择是使用动态 SQL 来创建一个视图,其中包含聚合在一起的所有必要表。 我们可以使用 SQL 服务器代理作业来定期维护视图,使用以下代码:

DECLARE @sql nvarchar(max) =
N'CREATE OR ALTER VIEW all_history AS
' +
(SELECT STRING_AGG(
    N'SELECT ' +
    QUOTENAME(p.name, '''') + N' AS name, ' +
    p.start_time + N' AS start_time, ' +
    p.end_time + N' AS end_time, * FROM ' +
    QUOTENAME(p.name)

  , CAST(N'
UNION ALL
' AS nvarchar(max))

FROM sqlth_partitions p
);

-- PRINT @sql;
EXEC (@sql);

现在您将拥有一个包含所有数据的视图,您可以正常查询它。


如果您使用的是没有STRING_AGG的 SQL 服务器版本,则需要FOR XML PATH方法。

我也会为您提供解决方案,我们还可以展示如何将其作为存储过程而不是视图来执行:

DECLARE @sql nvarchar(max) =
STUFF(
(SELECT
    CAST(NCHAR(10) AS nvarchar(max)) +
    N'UNION ALL' +
    NCHAR(10) +
    N'SELECT ' +
    QUOTENAME(p.name, '''') + N' AS name, ' +
    p.start_time + N' AS start_time, ' +
    p.end_time + N' AS end_time, * FROM ' +
    QUOTENAME(p.name)
FROM sqlth_partitions p
FOR XML PATH(''), TYPE

).value('text()[1]', 'nvarchar(max)'),
1, 11, N'');

-- PRINT @sql;
EXEC (@sql);

如您所见,由此创建一个完整的查询非常复杂和困难。

在得到朋友的帮助后在答案下方。 只需与社区分享它可能会有所帮助。

CREATE PROCEDURE dbo.RetrieveData @tagpath   NVARCHAR(255),

                             @begintime BIGINT,

                             @endtime   BIGINT

AS

DECLARE @tagId VARCHAR(50)



SET @tagId = (SELECT id

              FROM   sqlth_te

              WHERE  tagpath LIKE @tagpath)



DECLARE @PNAME NVARCHAR(100)

DECLARE @SQL NVARCHAR(max)

DECLARE mycursor CURSOR local fast_forward FOR

  SELECT pname AS 'PNAME'

  FROM   sqlth_partitions

  WHERE  end_time >= @endtime

         AND sqlth_partitions.start_time <= @begintime



OPEN mycursor



FETCH next FROM mycursor INTO @PNAME



SET @SQL = ''



WHILE @@FETCH_STATUS = 0

  BEGIN

      SET @SQL = @SQL + 'select floatvalue, t_stamp from '

                 + @PNAME + ' WHERE tagid = ' + @tagId + '  UNION  '



      FETCH next FROM mycursor INTO @PNAME

  END



SET @SQL = LEFT (@SQL, Len(@sql) - 8)



EXEC(@SQL)



IF Cursor_status('global', 'myCursor') >=- 1

  BEGIN

      DEALLOCATE mycursor

  END
go

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM