Querying Historical Data with the SQL Query Engine

After the SQL Query Engine stored procedures are registered in your SQL Server database, you can query Data Historian using T-SQL from any connected SQL client. This topic walks you through common query patterns using plausible sensor data from a manufacturing plant.

The examples below use SQL Server Management Studio. Any tool with a SQL Server connection—such as Power BI, SSRS, or a .NET application—can execute the same stored procedures.

Discovering Available Tags

Before querying data, use QE_GetAllPointNames to see which historian tags are available and review their metadata.

Example—return all available tags:

EXEC QE_GetAllPointNames

The result includes columns such as PointName, Path, DisplayName, EngineeringUnits, RangeLow, and RangeHigh, which you can use to identify the correct tag names for subsequent queries. Pass the value of the PointName column as @pointName in the queries that follow.

Example—filter to tags that contain "Temperature" in their path:

EXEC QE_GetAllPointNamesContains @pathContains = 'Temperature'

Querying Raw Historical Data

Use QE_GetHistoryRawModified to retrieve the unprocessed samples logged by Data Historian for a given tag and time range. This is equivalent to reading the raw archive data for that tag.

Example—retrieve all raw samples for a temperature sensor over a one-hour window:

EXEC QE_GetHistoryRawModified @pointName = 'Plant1\Line1:FurnaceTemperature', @startTimestamp = '2025-03-15 06:00:00', @endTimestamp = '2025-03-15 07:00:00'

The result set returns one row per logged sample, with columns PointName, Timestamp, Quality, and Value. The Quality column reports a status code for each sample, where 0 means Good. Learn more

If the data type of the tag is known, use a typed variant for better performance. For example, to retrieve the same data as double-precision floating-point values:

EXEC QE_GetHistoryRawModified_Double @pointName = 'Plant1\Line1:FurnaceTemperature', @startTimestamp = '2025-03-15 06:00:00', @endTimestamp = '2025-03-15 07:00:00'

Querying Aggregated Historical Data

Use QE_GetHdaAnalog to retrieve aggregated values for a numeric tag over a time range, divided into equal-length time buckets. This is useful for generating trend data, computing hourly averages, or reviewing minimum/maximum values for process monitoring.

Example—compute the hourly furnace temperature aggregates over a 24-hour period:

EXEC QE_GetHdaAnalog @pointName = 'Plant1\Line1:FurnaceTemperature', @startTimestamp = '2025-03-15 00:00:00', @endTimestamp = '2025-03-16 00:00:00', @resamplingInterval = 3600000

The @resamplingInterval parameter specifies the length of each time bucket, either as a number of milliseconds or as a time span such as 01:00:00. A value of 3600000 produces one result row per hour. Each row holds every aggregate at once: minimum, maximum, average, time-weighted average, time-weighted total, interpolated, last, delta, range, sum, and count. Each aggregate has its own group of columns, such as MINValue, MAXValue, and AVG_Value, with a matching Status column. There is no parameter for choosing an aggregate; select the columns you need from the result. For the full list of columns, see SQL Query Engine Stored Procedures.

Querying Multiple Points in One Call

Use QE_GetHdaAnalog5 to retrieve the same aggregate values for up to five points in a single result row per time bucket. This reduces the number of round trips to Data Historian when your report or analysis needs statistics for several points over the same time range and interval. The columns for each point carry its position as a suffix, such as MINValue1 for the first point and MINValue2 for the second.

Example—retrieve a full statistical summary of flow rate in hourly buckets over a production day:

EXEC QE_GetHdaAnalog5 @pointName1 = 'Plant1\Line1:CoolantFlowRate', @pointName2 = 'Plant1\Line1:CoolantReturnFlowRate', @pointName3 = 'Plant1\Line1:CoolantSupplyPressure', @pointName4 = 'Plant1\Line1:CoolantReturnPressure', @pointName5 = 'Plant1\Line1:CoolantTemperature', @startTimestamp = '2025-03-15 00:00:00', @endTimestamp = '2025-03-16 00:00:00', @resamplingInterval = 3600000

Querying Boolean Tag Data

For tags that log Boolean values, use QE_GetHdaBool or QE_GetHdaBool5.

Example—retrieve hourly state summary data for a pump running indicator:

EXEC QE_GetHdaBool @pointName = 'Plant1\CoolantPump1:Running', @startTimestamp = '2025-03-15 00:00:00', @endTimestamp = '2025-03-16 00:00:00', @resamplingInterval = 3600000

Combining Historian Data with SQL Data

Because the stored procedures return standard result sets, you can load the results into a temporary table and join them with relational data already in SQL Server. The following example retrieves hourly temperature aggregates, keeps the average from the AVG_Value column, and joins it with a shift schedule table to label each hour by shift.

Example:

-- Load historian aggregates into a temp table SELECT * INTO #TempHistory FROM OPENROWSET('SQLNCLI', 'Server=(local);Trusted_Connection=yes;', 'EXEC master.dbo.QE_GetHdaAnalog @pointName = ''Plant1\Line1:FurnaceTemperature'', @startTimestamp = ''2025-03-15 00:00:00'', @endTimestamp = ''2025-03-16 00:00:00'', @resamplingInterval = 3600000') -- Join with a shift schedule table SELECT h.[Timestamp], h.AVG_Value AS AvgTemperature, s.ShiftName FROM #TempHistory h JOIN dbo.ShiftSchedule s ON h.[Timestamp] >= s.ShiftStart AND h.[Timestamp] < s.ShiftEnd WHERE h.AVG_Status = 0 ORDER BY h.[Timestamp]

The OPENROWSET approach shown above requires the Ad Hoc Distributed Queries server option to be enabled on your SQL Server instance. Consult your database administrator if this option is not available in your environment.