Skip to main content

Documentation Portal

Examples of SQL queries for ODBC connections

This article shows some concrete examples which can help you set up your ODBC data source. More information can be found in this article.

The following examples assume that separate queries (values-STRING.sql) weren’t needed for pulling string tags.

list.sql examples

The first step in setting up an ODBC connector is to retrieve a unique list of tags. This query is entered into the list.sql file. The resulting query should return at least the "tagname" column and the "type" column. The query can optionally also return additional metadata in the "units" and the "description" columns, to help users recognize the data they're working with.

The query should not return duplicate entries for the tagname column. This will cause synch errors.

The simplest possible query, if the table you're working on already only has unique tagnames (no duplicates are present), and all tags are "analog" tags:

SELECT
    tagname, "analog" as type
FROM Table_1

If your database table contains different descriptions, units, and types for a single tag name, you can use the SQL function FIRST_VALUE() to get the first value in an ordered partition of a result set. The following query will return the first description, unit, and type it encounters for every distinct tagname.

SELECT DISTINCT 
    tagname,
    FIRST_VALUE(description) OVER (PARTITION BY tagname ORDER BY tagname) as description,
    FIRST_VALUE(units) OVER (PARTITION BY tagname ORDER BY tagname) as units,
    FIRST_VALUE(type) OVER (PARTITION BY tagname ORDER BY tagname) as type
FROM Table_1

Use a UNION statement to combine the output of two different tables (Table_1 and Table_2) into a single list.sql query.

SELECT
    tagname,
    description,
    type,
    units
FROM Table_1  
UNION
SELECT
    tagname,
    description,
    type,
    units
FROM Table_2 

Depending on the table schema, you might want to concatenate (combine) multiple columns to generate a unique tagname as shown below. You might also want to do the same for the description as well. Note that this will make it somewhat harder to reconcile data in TrendMiner with data in the SQL database, e.g. during troubleshooting. Therefore, it could be advised to create a table in the database that performs these steps, and have TrendMiner query that table directly.

SELECT DISTINCT
    (CAST(COMPONENT_NAME as varchar) + CAST(TANK_NUMBER as varchar)) as tagname,
    description,
    type,
    units
FROM Table_1

You might need to combine (join) multiple tables to generate a query output with all the necessary information for the list.sql file. In the query shown below, “TagName” and “Description” are both part of the table “_Tag”. However, the type and units are part of the “TagType” and “EngineeringUnit” tables respectively, pulled using the corresponding keys. Once again, for troubleshooting purposes, it might be better to construct a table like this in the data source immediately and use a simpler query in this list.sql setup.

SELECT DISTINCT
    TagName as tagname,
    Description as description,
    Unit as units,
    TagTypeName as type 
FROM _Tag
LEFT JOIN TagType ON _Tag.TagType=TagType.TagTypeKey
LEFT JOIN EngineeringUnit ON _Tag.EUKey=EngineeringUnit.EUKey 
values.sql examples

Once the tagnames are known to TrendMiner through the list.sql query, a query needs to be constructed that can retrieve data using three inputs: the tagname, the starts date for the query and the end date. These inputs are passed through as question marks in the query and should be in this order. The query should return an ordered list of timestamps and value pairs, with column names "ts" and "value" respectively. NULL values and other unexpected values such as NaN or other typical error flags should be filtered out.

The simplest possible query, if data is already preprocessed and column names already match the expectations, is shown below:

SELECT
    value, ts
FROM Table_1   
WHERE tagname = ? AND timestamp IS BETWEEN ? AND ? ORDER BY ts ASC  

If the values table contains entries (rows) with an empty (null) value, these can be filtered out with a values.sql query as follows.

SELECT
    value,
    timestamp as ts  
FROM Table_1   
WHERE tagname = ? AND timestamp IS BETWEEN ? AND ? AND value IS NOT NULL ORDER BY timestamp ASC

In case there is more than one value for the same timestamp available (which, in itself should physically not be possible, but could happen due to rounding errors), it is required to let TrendMiner know which one to pick to avoid unpredictable results. The following query will return the first “value” encountered for a given tag and date range.

SELECT DISTINCT
    FIRST_VALUE(value) OVER (PARTITION BY timestamp ORDER BY value desc) as value,
    timestamp as ts  
FROM Table_1  
WHERE tagname = ? AND timestamp IS BETWEEN ? AND ? ORDER BY timestamp ASC

In this case, assuming the values and timestamps originate from the same table, the values.sql query might look as follows

SELECT
    value2,
    FORMAT(value2, 'N', 'en-us') as value2_US_Format,
    FORMAT(value2, 'N', 'de-de') as value2_DE_Format
FROM Table_1

The output will look as follows:

SQL_Queries.png