To start the TDengine server, run the command below in terminal:
```cmd
```cmd
./build/bin/taosd -c test/cfg
```
In another terminal, use the TDengine shell to connect the server:
...
...
@@ -88,7 +88,9 @@ drop database db;
```
# Developing with TDengine
TDengine provides abundant developing tools for users to develop on TDengine. Follow the links below to find your desired connectors.
### Official Connectors
TDengine provides abundant developing tools for users to develop on TDengine. Follow the links below to find your desired connectors and relevant documentation.
<pre><codeclass='language-mysql'lang='mysql'>SELECT TBNAME,[TAG_NAME,…] FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<pre><codeclass="mysql language-mysql">SELECT TBNAME,[TAG_NAME,…] FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(TBNAME) FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<p>统计属于某个STable并满足查询条件的子表的数量</p>
</li>
<pre><codeclass="mysql language-mysql">SELECT COUNT(TBNAME) FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<p> 不使用GROUP BY的查询将会对超级表下所有满足筛选条件的表按时间进行聚合,结果输出默认是按照时间戳单调递增输出,用户可以使用ORDER BY _c0 ASC|DESC选择查询结果时间戳的升降排序;使用GROUP BY <tag_name> 的聚合查询会按照tags进行分组,并对每个组内的数据分别进行聚合,输出结果为各个组的聚合结果,组间的排序可以由ORDER BY <tag_name> 语句指定,每个分组内部,时间序列是单调递增的。 </p>
<p>不使用GROUP BY的查询将会对超级表下所有满足筛选条件的表按时间进行聚合,结果输出默认是按照时间戳单调递增输出,用户可以使用ORDER BY _c0 ASC|DESC选择查询结果时间戳的升降排序;使用GROUP BY <tag_name> 的聚合查询会按照tags进行分组,并对每个组内的数据分别进行聚合,输出结果为各个组的聚合结果,组间的排序可以由ORDER BY <tag_name> 语句指定,每个分组内部,时间序列是单调递增的。 </p>
GROUP BY location, type</code></pre><ahref='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
<tr><th>Operation</th><th>Note</th><th>Applicable Data Types</th></tr></thead>
<tbody><tr><td>></td><td>larger than</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td><</td><td>smaller than</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td>>=</td><td>larger than or equal to</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td><=</td><td>smaller than or equal to</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td>=</td><td>equal to</td><td>all types</td></tr><tr><td><></td><td>not equal to</td><td>all types</td></tr><tr><td>%</td><td>match with any char sequences</td><td><strong><code>binary</code></strong><strong><code>nchar</code></strong></td></tr><tr><td>_</td><td>match with a single char</td><td><strong><code>binary</code></strong><strong><code>nchar</code></strong></td></tr></tbody>
</table></figure></figure>
<tr>
<th>Operation</th>
<th>Note</th>
<th>Applicable Data Types</th>
</tr>
</thead>
<tbody>
<tr>
<td>></td>
<td>larger than</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td><</td>
<td>smaller than</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td>>=</td>
<td>larger than or equal to</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td><=</td>
<td>smaller than or equal to</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
<pre><codeclass='language-mysql'lang='mysql'>SELECT * FROM tb1 WHERE ts >'2018-06-01 08:00:00.000' AND ts <= '2018-06-02 08:00:00.000' AND col3 LIKE '%nny' ORDER BY ts DESC</code></pre>
</li>
<pre><codeclass="mysql language-mysql">SELECT * FROM tb1 WHERE ts >= NOW - 1h</code></pre></li>
<pre><codeclass="mysql language-mysql">SELECT * FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' AND ts <= '2018-06-02 08:00:00.000' AND col3 LIKE '%nny' ORDER BY ts DESC</code></pre></li>
<pre><codeclass='language-mysql'lang='mysql'>SELECT (col1 + col2) AS 'complex' FROM tb1 WHERE ts >'2018-06-01 08:00:00.000' and col2 > 1.2 LIMIT 10 OFFSET 5</code></pre>
</li>
<pre><codeclass="mysql language-mysql">SELECT (col1 + col2) AS 'complex' FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' and col2 > 1.2 LIMIT 10 OFFSET 5</code></pre></li>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*) FROM tb1 WHERE ts >= NOW - 10m AND col2 > 3.14 >> /home/testoutpu.csv</code></pre>
</li>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*) FROM tb1 WHERE ts >= NOW - 10m AND col2 > 3.14 >> /home/testoutpu.csv</code></pre></li>
</ul>
<aclass='anchor'id='SQL函数'></a><h2>SQL函数</h2>
<aclass='anchor'id='聚合函数'></a><h3>聚合函数</h3>
<p>TDengine支持针对数据的聚合查询。提供支持的聚合和提取函数如下表:</p>
<ul>
<li><p><strong>COUNT</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]</code></pre>
<p>Continuous Query is a query executed by TDengine periodically with a sliding window, it is a simplified stream computing driven by timers, not by events. Continuous query can be applied to a table or a STable, and the result set can be passed to the application directly via call back function, or written into a new table in TDengine. The query is always executed on a specified time window (window size is specified by parameter interval), and this window slides forward while time flows (the sliding period is specified by parameter sliding). </p>
<p>Continuous query is defined by TAOS SQL, there is nothing special. One of the best applications is downsampling. Once it is defined, at the end of each cycle, the system will execute the query, pass the result to the application or write it to a database. </p>
<p>If historical data pints are inserted into the stream, the query won't be re-executed, and the result set won't be updated. If the result set is passed to the application, the application needs to keep the status of continuous query, the server won't maintain it. If application re-starts, it needs to decide the time where the stream computing shall be started.</p>
<p>If historical data pints are inserted into the stream, the query won't be re-executed, and the result set won't be updated. If the result set is passed to the application, the application needs to keep the status of continuous query, the server won't maintain it. If application re-starts, it needs to decide the time where the stream computing shall be started.</p>
<h4>How to use continuous query</h4>
<ul>
<li><p>Pass result set to application</p>
<p>Application shall use API taos_stream (details in connector section) to start the stream computing. Inside the API, the SQL syntax is:</p>
<pre><codeclass='language-sql'lang='sql'>SELECT aggregation FROM [table_name | stable_name]
<pre><codeclass="sql language-sql">SELECT aggregation FROM [table_name | stable_name]
<p>where the new keyword INTERVAL specifies the window size, and SLIDING specifies the sliding period. If parameter sliding is not specified, the sliding period will be the same as window size. The minimum window size is 10ms. The sliding period shall not be larger than the window size. If you set a value larger than the window size, the system will adjust it to window size automatically.</p>
<p>For example:</p>
<pre><codeclass='language-sql'lang='sql'>SELECT COUNT(*) FROM FOO_TABLE
<pre><codeclass="sql language-sql">SELECT COUNT(*) FROM FOO_TABLE
INTERVAL(1M) SLIDING(30S)</code></pre>
<p>The above SQL statement will count the number of records for the past 1-minute window every 30 seconds.</p>
</li>
<p>The above SQL statement will count the number of records for the past 1-minute window every 30 seconds.</p></li>
<li><p>Save the result into a database</p>
<p>If you want to save the result set of stream computing into a new table, the SQL shall be: </p>
<pre><codeclass='language-sql'lang='sql'>CREATE TABLE table_name AS
<pre><codeclass="sql language-sql">CREATE TABLE table_name AS
SELECT aggregation from [table_name | stable_name]
<p>Also, you can set the time range to execute the continuous query. If no range is specified, the continuous query will be executed forever. For example, the following continuous query will be executed from now and will stop in one hour.</p>
<pre><codeclass='language-sql'lang='sql'>CREATE TABLE QUERY_RES AS
<pre><codeclass="sql language-sql">CREATE TABLE QUERY_RES AS
SELECT COUNT(*) FROM FOO_TABLE
WHERE TS > NOW AND TS <= NOW + 1H
INTERVAL(1M) SLIDING(30S) </code></pre>
</li>
INTERVAL(1M) SLIDING(30S) </code></pre></li>
</ul>
<aclass='anchor'id='Manage-the-Continuous-Query'></a><h3>Manage the Continuous Query</h3>
<p>Inside TDengine shell, you can use the command "show streams" to list the ongoing continuous queries, the command "kill stream" to kill a specific continuous query. </p>
<p>Inside TDengine shell, you can use the command "show streams" to list the ongoing continuous queries, the command "kill stream" to kill a specific continuous query. </p>
<p>If you drop a table generated by the continuous query, the query will be removed too.</p>
<p>Time series data is a sequence of data points over time. Inside a table, the data points are stored in order of timestamp. Also, there is a data retention policy, the data points will be removed once their lifetime is passed. From another view, a table in DTengine is just a standard message queue. </p>
<p>To reduce the development complexity and improve data consistency, TDengine provides the pub/sub functionality. To publish a message, you simply insert a record into a table. Compared with popular messaging tool Kafka, you subscribe to a table or a SQL query statement, instead of a topic. Once new data points arrive, TDengine will notify the application. The process is just like Kafka. </p>
<p>The detailed API will be introduced in the <ahref=''>connectors</a> section. </p>
<p>The detailed API will be introduced in the <ahref="https://www.taosdata.com/en/documentation/advanced-features/">connectors</a> section. </p>
<aclass='anchor'id='Caching'></a><h2>Caching</h2>
<p>TDengine allocates a fixed-size buffer in memory, the newly arrived data will be written into the buffer first. Every device or table gets one or more memory blocks. For typical IoT scenarios, the hot data shall always be newly arrived data, they are more important for timely analysis. Based on this observation, TDengine manages the cache blocks in First-In-First-Out strategy. If no enough space in the buffer, the oldest data will be saved into hard disk first, then be overwritten by newly arrived data. TDengine also guarantees every device can keep at least one block of data in the buffer. </p>
<p>By this design, the application can retrieve the latest data from each device super-fast, since they are all available in memory. You can use last or last_row function to return the last data record. If the super table is used, it can be used to return the last data records of all or a subset of devices. For example, to retrieve the latest temperature from thermometers in located Beijing, execute the following SQL </p>
<pre><codeclass='language-mysql'lang='mysql'>select last(*) from thermometers where location=’beijing’</code></pre>
<pre><codeclass="mysql language-mysql">select last(*) from thermometers where location=’beijing’</code></pre>
<p>By this design, caching tool, like Redis, is not needed in the system. It will reduce the complexity of the system. </p>
<p>TDengine creates one or more virtual nodes(vnode) in each data node. Each vnode contains data for multiple tables and has its own buffer. The buffer of a vnode is fully separated from the buffer of another vnode, not shared. But the tables in a vnode share the same buffer. </p>
<p>System configuration parameter cacheBlockSize configures the cache block size in bytes, and another parameter cacheNumOfBlocks configures the number of cache blocks. The total memory for the buffer of a vnode is cacheBlockSize \times cacheNumOfBlocks. Another system parameter numOfBlocksPerMeter configures the maximum number of cache blocks a table can use. When you create a database, you can specify these parameters. </p>
<p>System configuration parameter cacheBlockSize configures the cache block size in bytes, and another parameter cacheNumOfBlocks configures the number of cache blocks. The total memory for the buffer of a vnode is $cacheBlockSize \times cacheNumOfBlocks$. Another system parameter numOfBlocksPerMeter configures the maximum number of cache blocks a table can use. When you create a database, you can specify these parameters. </p><ahref='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
<p>The async API to fetch a result row. <em>res</em> is the result handle. <em>fp</em> is the callback function. <em>param</em> is a user-defined structure to pass to <em>fp</em>. The third parameter of the callback function is a single result row, which is different from that of <em>taos_fetch_rows_a</em> API. With this API, it is not necessary to call <em>taos_fetch_row</em> to retrieve each result row, which is handier than <em>taos_fetch_rows_a</em> but less efficient.</p></li>
</ul>
<p>Applications may apply operations on multiple tables. However, <strong>it is important to make sure the operations on the same table are serialized</strong>. That means after sending an insert request in a table to the server, no operations on the table are allowed before a request is received.</p>
<p>Applications may apply operations on multiple tables. However, <strong>it is important to make sure the operations on the same table are serialized</strong>. That means after sending an insert request in a table to the server, no operations on the table are allowed before a response is received.</p>
result.pretty(); //logs the results to the console as if you were in the taos shell
});</code></pre>
<p>You can also query by binding parameters to a query by filling in the question marks in a string as so. The query will automatically parse what was binded and convert it to the proper format for use with TDengine</p>
<pre><codeclass="javascript language-javascript">var query = cursor.query('select * from meterinfo.meters where ts <= ? and areaid = ?').bind(new Date(), 5);
<pre><codeclass="javascript language-javascript">var query = cursor.query('select * from meterinfo.meters where ts <= ? and areaid = ?;').bind(new Date(), 5);
query.execute().then(function(result) {
result.pretty();
})</code></pre>
<p>The TaosQuery object can also be immediately executed upon creation by passing true as the second argument, returning a promise instead of a TaosQuery.</p>
<pre><codeclass="javascript language-javascript">var promise = cursor.query('select * from meterinfo.meters where v1 = 30', true)
<pre><codeclass="javascript language-javascript">var promise = cursor.query('select * from meterinfo.meters where v1 = 30;', true)
promise.then(function(result) {
result.pretty();
})</code></pre>
<h4>Async functionality</h4>
<p>Coming soon</p>
<p>Async queries can be performed using the same functions such as <code>cursor.execute</code>, <code>cursor.query</code>, but now with <code>_a</code> appended to them.</p>
<p>Say you want to execute an two async query on two seperate tables, using <code>cursor.query_a</code>, you can do that and get a TaosQuery object, which upon executing with the <code>execute_a</code> function, returns a promise that resolves with a TaosResult object.</p>
<pre><codeclass="javascript language-javascript">var promise1 = cursor.query_a('select count(*), avg(v1), avg(v2) from meter1;').execute_a()
var promise2 = cursor.query_a('select count(*), avg(v1), avg(v2) from meter2;').execute_a();
promise1.then(function(result) {
result.pretty();
})
promise2.then(function(result) {
result.pretty();
})</code></pre>
<h3>Example</h3>
<p>An example of using the NodeJS connector to create a table with weather data and create and execute queries can be found <ahref="https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example.js">here</a> (The preferred method for using the connector)</p>
<p>An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found <ahref="https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js">here</a></p><ahref='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
<!DOCTYPE html><htmllang='en'><head><title>Documentation | Taos Data</title><metaname='description'content='TDengine is an open-source big data platform for IoT. Along with a 10x faster time-series database, it provides caching, stream computing, message queuing, and other functionalities. It is designed and optimized for Internet of Things, Connected Cars, and Industrial IoT. Read the documentation for TDengine here to get started right away.'><metaname='keywords'content='TDengine, Big Data, Open Source, IoT, Connected Cars, Industrial IoT, time-series database, caching, stream computing, message queuing, IT infrastructure monitoring, application performance monitoring, Internet of Things,TAOS Data, Documentation, programming, coding, syntax, frequently asked questions, questions, faq'><metaname='title'content='Documentation | Taos Data'><metaproperty='og:site_name'content='Taos Data'/><metaproperty='og:title'content='Documentation | Taos Data'/><metaproperty='og:type'content='article'/><metaproperty='og:url'content='https://www.taosdata.com/en/documentation/super-table/index.php'/><metaproperty='og:description'content='TDengine is an open-source big data platform for IoT. Along with a 10x faster time-series database, it provides caching, stream computing, message queuing, and other functionalities. It is designed and optimized for Internet of Things, Connected Cars, and Industrial IoT. Read the documentation for TDengine here to get started right away.'/><linkrel='canonical'href='https://www.taosdata.com/en/documentation/super-table/index.php'/><script src='../lib/jquery-3.4.1.min.js'type='application/javascript'></script><linkhref='../lib/bootstrap.min.css'rel='stylesheet'><linkhref='../styles/base.min.css'rel='stylesheet'><linkrel='stylesheet'href='../lib/docs/taosdataprettify.css'><linkrel='stylesheet'href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><divclass='container-fluid'><mainclass='content-wrapper'><sectionclass='documentation'><ahref='../index.html'>Back</a><h1>STable: Super Table</h1>
<p>"One Table for One Device" design can improve the insert/query performance significantly for a single device. But it has a side effect, the aggregation of multiple tables becomes hard. To reduce the complexity and improve the efficiency, TDengine introduced a new concept: STable (Super Table). </p>
<p>"One Table for One Device" design can improve the insert/query performance significantly for a single device. But it has a side effect, the aggregation of multiple tables becomes hard. To reduce the complexity and improve the efficiency, TDengine introduced a new concept: STable (Super Table). </p>
<aclass='anchor'id='What-is-a-Super-Table'></a><h2>What is a Super Table</h2>
<p>STable is an abstract and a template for a type of device. A STable contains a set of devices (tables) that have the same schema or data structure. Besides the shared schema, a STable has a set of tags, like the model, serial number and so on. Tags are used to record the static attributes for the devices and are used to group a set of devices (tables) for aggregation. Tags are metadata of a table and can be added, deleted or changed. </p>
<p>TDengine does not save tags as a part of the data points collected. Instead, tags are saved as metadata. Each table has a set of tags. To improve query performance, tags are all cached and indexed. One table can only belong to one STable, but one STable may contain many tables. </p>
<p>Like a table, you can create, show, delete and describe STables. Most query operations on tables can be applied to STable too, including the aggregation and selector functions. For queries on a STable, if no tags filter, the operations are applied to all the tables created via this STable. If there is a tag filter, the operations are applied only to a subset of the tables which satisfy the tag filter conditions. It will be very convenient to use tags to put devices into different groups for aggregation.</p>
<aclass='anchor'id='Create-a-STable'></a><h2>Create a STable</h2>
<p>Similiar to creating a standard table, syntax is: </p>
<p>The above statement creates a STable thermometer with two tag "location" and "type"</p>
<p>The above statement creates a STable thermometer with two tag "location" and "type"</p>
<aclass='anchor'id='Create-a-Table-via-STable'></a><h2>Create a Table via STable</h2>
<p>To create a table for a device, you can use a STable as its template and assign the tag values. The syntax is:</p>
<pre><codeclass='language-mysql'lang='mysql'>CREATE TABLE <tb_name> USING <stb_name> TAGS (tag_value1,...)</code></pre>
<pre><codeclass="mysql language-mysql">CREATE TABLE <tb_name> USING <stb_name> TAGS (tag_value1,...)</code></pre>
<p>You can create any number of tables via a STable, and each table may have different tag values. For example, you create five tables via STable thermometer below:</p>
<pre><codeclass='language-mysql'lang='mysql'> create table t1 using thermometer tags (‘beijing’, 10);
<pre><codeclass="mysql language-mysql"> create table t1 using thermometer tags (‘beijing’, 10);
create table t2 using thermometer tags (‘beijing’, 20);
create table t3 using thermometer tags (‘shanghai’, 10);
create table t4 using thermometer tags (‘shanghai’, 20);
create table t5 using thermometer tags (‘new york’, 10);</code></pre>
<aclass='anchor'id='Aggregate-Tables-via-STable'></a><h2>Aggregate Tables via STable</h2>
<p>You can group a set of tables together by specifying the tags filter condition, then apply the aggregation operations. The result set can be grouped and ordered based on tag value. Syntax is:</p>
WHERE <tag_name><[=|<=|>=|<>] values..> ([AND|OR] …)
INTERVAL (<time range>)
...
...
@@ -44,54 +43,53 @@ tags (location binary(20), type int)</code></pre>
OFFSET <record_offset></code></pre>
<p>For the time being, STable supports only the following aggregation/selection functions: <em>sum, count, avg, first, last, min, max, top, bottom</em>, and the projection operations, the same syntax as a standard table. Arithmetic operations are not supported, embedded queries not either. </p>
<p><em>INTERVAL</em> is used for the aggregation over a time range.</p>
<p>If <em>GROUP BY</em> is not used, the aggregation is applied to all the selected tables, and the result set is output in ascending order of the timestamp, but you can use "<em>ORDER BY _c0 ASC|DESC</em>" to specify the order you like. </p>
<p>If <em>GROUP BY <tag_name></em> is used, the aggregation is applied to groups based on tags. Each group is aggregated independently. Result set is a group of aggregation results. The group order is decided by <em>ORDER BY <tag_name></em>. Inside each group, the result set is in the ascending order of the time stamp. </p>
<p>If <em>GROUP BY</em> is not used, the aggregation is applied to all the selected tables, and the result set is output in ascending order of the timestamp, but you can use "<em>ORDER BY _c0 ASC|DESC</em>" to specify the order you like. </p>
<p>If <em>GROUP BY <tag_name></em> is used, the aggregation is applied to groups based on tags. Each group is aggregated independently. Result set is a group of aggregation results. The group order is decided by <em>ORDER BY <tag_name></em>. Inside each group, the result set is in the ascending order of the time stamp. </p>
<p><em>SLIMIT/SOFFSET</em> are used to limit the number of groups and starting group number.</p>
<p><em>LIMIT/OFFSET</em> are used to limit the number of records in a group and the starting rows.</p>
<p>Check the average, maximum, and minimum temperatures of Beijing and Shanghai, and group the result set by location and type. The SQL statement shall be:</p>
<p>List the number of records, average, maximum, and minimum temperature every 10 minutes for the past 24 hours for all the thermometers located in Beijing with type 10. The SQL statement shall be:</p>
<p>Insert operation will fail if the table is not created yet. But for STable, TDengine can create the table automatically if the application provides the STable name, table name and tags' value when inserting data points. The syntax is:</p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO <tb_name> USING <stb_name> TAGS (<tag1_value>, ...) VALUES (field_value, ...) (field_value, ...) ... <tb_name2> USING <stb_name2> TAGS(<tag1_value2>, ...) VALUES (<field1_value1>, ...) ...;</code></pre>
<p>Insert operation will fail if the table is not created yet. But for STable, TDengine can create the table automatically if the application provides the STable name, table name and tags' value when inserting data points. The syntax is:</p>
<pre><codeclass="mysql language-mysql">INSERT INTO <tb_name> USING <stb_name> TAGS (<tag1_value>, ...) VALUES (field_value, ...) (field_value, ...) ... <tb_name2> USING <stb_name2> TAGS(<tag1_value2>, ...) VALUES (<field1_value1>, ...) ...;</code></pre>
<p>When inserting data points into table tb_name, the system will check if table tb_name is created or not. If it is already created, the data points will be inserted as usual. But if the table is not created yet, the system will create the table tb_bame using STable stb_name as the template with the tags. Multiple tables can be specified in the SQL statement. </p>
<aclass='anchor'id='Management-of-STables'></a><h2>Management of STables</h2>
<p>After you can create a STable, you can describe, delete, change STables. This section lists all the supported operations.</p>
<aclass='anchor'id='Show-STables-in-current-DB'></a><h3>Show STables in current DB</h3>
<p>It lists all STables in current DB, including the name, created time, number of fileds, number of tags, and number of tables which are created via this STable. </p>
<aclass='anchor'id='Describe-a-STable'></a><h3>Describe a STable</h3>
<p>To delete a STable, all the tables created via this STable shall be deleted first, otherwise, it will fail.</p>
<aclass='anchor'id='List-the-Associated-Tables-of-a-STable'></a><h3>List the Associated Tables of a STable</h3>
<pre><codeclass='language-mysql'lang='mysql'>SELECT TBNAME,[TAG_NAME,…] FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<pre><codeclass="mysql language-mysql">SELECT TBNAME,[TAG_NAME,…] FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<p>It will list all the tables which satisfy the tag filter conditions. The tables are all created from this specific STable. TBNAME is a new keyword introduced, it is the table name associated with the STable. </p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(TBNAME) FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<pre><codeclass="mysql language-mysql">SELECT COUNT(TBNAME) FROM <stable_name> WHERE <tag_name><[=|=<|>=|<>] values..> ([AND|OR] …)</code></pre>
<p>The above SQL statement will list the number of tables in a STable, which satisfy the filter condition.</p>
<aclass='anchor'id='Management-of-Tags'></a><h2>Management of Tags</h2>
<p>You can add, delete and change the tags for a STable, and you can change the tag value of a table. The SQL commands are listed below. </p>
<aclass='anchor'id='Add-a-Tag'></a><h3>Add a Tag</h3>
<pre><codeclass='language-mysql'lang='mysql'>ALTER TABLE <stable_name> ADD TAG <new_tag_name><TYPE></code></pre>
<pre><codeclass="mysql language-mysql">ALTER TABLE <stable_name> ADD TAG <new_tag_name><TYPE></code></pre>
<p>It adds a new tag to the STable with a data type. The maximum number of tags is 6. </p>
<aclass='anchor'id='Drop-a-Tag'></a><h3>Drop a Tag</h3>
<pre><codeclass='language-mysql'lang='mysql'>ALTER TABLE <stable_name> DROP TAG <tag_name></code></pre>
<pre><codeclass="mysql language-mysql">ALTER TABLE <stable_name> DROP TAG <tag_name></code></pre>
<p>It drops a tag from a STable. The first tag could not be deleted, and there must be at least one tag.</p>
<aclass='anchor'id='Change-a-Tag's-Name'></a><h3>Change a Tag's Name</h3>
<pre><codeclass='language-mysql'lang='mysql'>ALTER TABLE <stable_name> CHANGE TAG <old_tag_name><new_tag_name></code></pre>
<aclass='anchor'id='Change-a-Tag's-Name'></a><h3>Change a Tag's Name</h3>
<pre><codeclass="mysql language-mysql">ALTER TABLE <stable_name> CHANGE TAG <old_tag_name><new_tag_name></code></pre>
<p>It changes the name of a tag from old to new. </p>
<aclass='anchor'id='Change-the-Tag's-Value'></a><h3>Change the Tag's Value</h3>
<pre><codeclass='language-mysql'lang='mysql'>ALTER TABLE <table_name> SET TAG <tag_name>=<new_tag_value></code></pre>
<p>It changes a table's tag value to a new one. </p>
<aclass='anchor'id='Change-the-Tag's-Value'></a><h3>Change the Tag's Value</h3>
<pre><codeclass="mysql language-mysql">ALTER TABLE <table_name> SET TAG <tag_name>=<new_tag_value></code></pre>
<p>It changes a table's tag value to a new one. </p><ahref='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
<p>TDengine provides a SQL like query language to insert or query data. You can execute the SQL statements through TDengine Shell, or through C/C++, Java(JDBC), Python, Restful, Go APIs to interact with the <code>taosd</code> service.</p>
<p>Before reading through, please have a look at the conventions used for syntax descriptions here in this documentation.</p>
<ul>
<li>Squared brackets ("[]") indicate optional arguments or clauses</li>
<li>Curly braces ("{}") indicate that one member from a set of choices in the braces must be chosen</li>
<li>A single verticle line ("|") works a separator for multiple optional args or clauses</li>
<li>Dots ("…") means repeating for as many times</li>
<li>Squared brackets ("[]") indicate optional arguments or clauses</li>
<li>Curly braces ("{}") indicate that one member from a set of choices in the braces must be chosen</li>
<li>A single verticle line ("|") works a separator for multiple optional args or clauses</li>
<li>Dots ("…") means repeating for as many times</li>
<p>The timestamp is the most important data type in TDengine. The first column of each table must be <strong><code>TIMESTAMP</code></strong> type, but other columns can also be <strong><code>TIMESTAMP</code></strong> type. The following rules for timestamp: </p>
<ul>
<li>String Format: <code>'YYYY-MM-DD HH:mm:ss.MS'</code>, which represents the year, month, day, hour, minute and second and milliseconds. For example,<code>'2017-08-12 18:52:58.128'</code> is a valid timestamp string. Note: timestamp string must be quoted by either single quote or double quote. </li>
<li>Epoch Time: a timestamp value can also be a long integer representing milliseconds since the epoch. For example, the values in the above example can be represented as an epoch <code>1502535178128</code> in milliseconds. Please note the epoch time doesn't need any quotes.</li>
<li>Internal Function<strong><code>NOW</code></strong> : this is the current time of the server</li>
<li>If timestamp is 0 when inserting a record, timestamp will be set to the current time of the server</li>
<li>Arithmetic operations can be applied to timestamp. For example: <code>now-2h</code> represents a timestamp which is 2 hours ago from the current server time. Units include <code>a</code> (milliseconds), <code>s</code> (seconds), <code>m</code> (minutes), <code>h</code> (hours), <code>d</code> (days), <code>w</code> (weeks), <code>n</code> (months), <code>y</code> (years). <strong><code>NOW</code></strong> can be used in either insertions or queries. </li>
<li><p>String Format: <code>'YYYY-MM-DD HH:mm:ss.MS'</code>, which represents the year, month, day, hour, minute and second and milliseconds. For example,<code>'2017-08-12 18:52:58.128'</code> is a valid timestamp string. Note: timestamp string must be quoted by either single quote or double quote. </p></li>
<li><p>Epoch Time: a timestamp value can also be a long integer representing milliseconds since the epoch. For example, the values in the above example can be represented as an epoch <code>1502535178128</code> in milliseconds. Please note the epoch time doesn't need any quotes.</p></li>
<li><p>Internal Function<strong><code>NOW</code></strong> : this is the current time of the server</p></li>
<li><p>If timestamp is 0 when inserting a record, timestamp will be set to the current time of the server</p></li>
<li><p>Arithmetic operations can be applied to timestamp. For example: <code>now-2h</code> represents a timestamp which is 2 hours ago from the current server time. Units include <code>a</code> (milliseconds), <code>s</code> (seconds), <code>m</code> (minutes), <code>h</code> (hours), <code>d</code> (days), <code>w</code> (weeks), <code>n</code> (months), <code>y</code> (years). <strong><code>NOW</code></strong> can be used in either insertions or queries. </p></li>
</ul>
<p>Default time precision is millisecond, you can change it to microseocnd by setting parameter enableMicrosecond in <ahref=''>system configuration</a>. For epoch time, the long integer shall be microseconds since the epoch. For the above string format, MS shall be six digits. </p>
<p>Default time precision is millisecond, you can change it to microseocnd by setting parameter enableMicrosecond in <ahref="../administrator/#Configuration-on-Server">system configuration</a>. For epoch time, the long integer shall be microseconds since the epoch. For the above string format, MS shall be six digits. </p>
<p>The full list of data types is listed below. For string types of data, we will use <strong><em>M</em></strong> to indicate the maximum length of that type.</p>
<tbody><tr><td>1</td><tdstyle='text-align:center;'>TINYINT</td><tdstyle='text-align:center;'>1</td><td>A nullable integer type with a range of [-127, 127]</td></tr><tr><td>2</td><tdstyle='text-align:center;'>SMALLINT</td><tdstyle='text-align:center;'>2</td><td>A nullable integer type with a range of [-32767, 32767]</td></tr><tr><td>3</td><tdstyle='text-align:center;'>INT</td><tdstyle='text-align:center;'>4</td><td>A nullable integer type with a range of [-2^{31}+1, 2^{31}-1 ]</td></tr><tr><td>4</td><tdstyle='text-align:center;'>BIGINT</td><tdstyle='text-align:center;'>8</td><td>A nullable integer type with a range of [-2^{59}, 2^{59} ]</td></tr><tr><td>5</td><tdstyle='text-align:center;'>FLOAT</td><tdstyle='text-align:center;'>4</td><td>A standard nullable float type with 6 -7 significant digits and a range of [-3.4 e 38, 3.4 e 38]</td></tr><tr><td>6</td><tdstyle='text-align:center;'>DOUBLE</td><tdstyle='text-align:center;'>8</td><td>A standard nullable double float type with 15-16 significant digits and a range of [-1.7e308, 1.7e308]</td></tr><tr><td>7</td><tdstyle='text-align:center;'>BOOL</td><tdstyle='text-align:center;'>1</td><td>A nullable boolean type, [<strong><code>true</code></strong>, <strong><code>false</code></strong>]</td></tr><tr><td>8</td><tdstyle='text-align:center;'>TIMESTAMP</td><tdstyle='text-align:center;'>8</td><td>A nullable timestamp type with the same usage as the primary column timestamp</td></tr><tr><td>9</td><tdstyle='text-align:center;'>BINARY(<em>M</em>)</td><tdstyle='text-align:center;'><em>M</em></td><td>A nullable string type whose length is <em>M</em>, any exceeded chars will be automatically truncated. This type of string only supports ASCii encoded chars.</td></tr><tr><td>10</td><tdstyle='text-align:center;'>NCHAR(<em>M</em>)</td><tdstyle='text-align:center;'>4 * <em>M</em></td><td>A nullable string type whose length is <em>M</em>, any exceeded chars will be truncated. The <strong><code>NCHAR</code></strong> type supports Unicode encoded chars.</td></tr></tbody>
</table></figure></figure>
<p>All the keywords in a SQL statement are case-insensitive, but strings values are case-sensitive and must be quoted by a pair of <code>'</code> or <code>"</code>. To quote a <code>'</code> or a <code>"</code> , you can use the escape character <code>\</code>.</p>
<tr>
<th></th>
<thstyle="text-align:center;">Data Type</th>
<thstyle="text-align:center;">Bytes</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<tdstyle="text-align:center;">TINYINT</td>
<tdstyle="text-align:center;">1</td>
<td>A nullable integer type with a range of [-127, 127]</td>
</tr>
<tr>
<td>2</td>
<tdstyle="text-align:center;">SMALLINT</td>
<tdstyle="text-align:center;">2</td>
<td>A nullable integer type with a range of [-32767, 32767]</td>
</tr>
<tr>
<td>3</td>
<tdstyle="text-align:center;">INT</td>
<tdstyle="text-align:center;">4</td>
<td>A nullable integer type with a range of [-2^31+1, 2^31-1 ]</td>
</tr>
<tr>
<td>4</td>
<tdstyle="text-align:center;">BIGINT</td>
<tdstyle="text-align:center;">8</td>
<td>A nullable integer type with a range of [-2^59, 2^59 ]</td>
</tr>
<tr>
<td>5</td>
<tdstyle="text-align:center;">FLOAT</td>
<tdstyle="text-align:center;">4</td>
<td>A standard nullable float type with 6 -7 significant digits and a range of [-3.4E38, 3.4E38]</td>
</tr>
<tr>
<td>6</td>
<tdstyle="text-align:center;">DOUBLE</td>
<tdstyle="text-align:center;">8</td>
<td>A standard nullable double float type with 15-16 significant digits and a range of [-1.7E308, 1.7E308]</td>
<td>A nullable string type whose length is <em>M</em>, any exceeded chars will be automatically truncated. This type of string only supports ASCii encoded chars.</td>
<td>A nullable string type whose length is <em>M</em>, any exceeded chars will be truncated. The <strong><code>NCHAR</code></strong> type supports Unicode encoded chars.</td>
</tr>
</tbody>
</table></figure>
<p>All the keywords in a SQL statement are case-insensitive, but strings values are case-sensitive and must be quoted by a pair of <code>'</code> or <code>"</code>. To quote a <code>'</code> or a <code>"</code> , you can use the escape character <code>\</code>.</p>
<pre><codeclass='language-mysql'lang='mysql'>CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep]</code></pre>
<p>Option: <code>KEEP</code> is used for data retention policy. The data records will be removed once keep-days are passed. There are more parameters related to DB storage, please check <ahref=''>system configuration</a>.</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep]</code></pre>
<p>Option: <code>KEEP</code> is used for data retention policy. The data records will be removed once keep-days are passed. There are more parameters related to DB storage, please check <ahref="../administrator/#Configuration-on-Server">system configuration</a>.</p></li>
<p>Note: 1) the first column must be timstamp, and system will set it as the primary key; 2) the record size is limited to 4096 bytes; 3) for binary or nachr data type, the length shall be specified, for example, binary(20), it means 20 bytes.</p>
<p>Note: 1) the first column must be timstamp, and system will set it as the primary key; 2) the record size is limited to 4096 bytes; 3) for binary or nachr data type, the length shall be specified, for example, binary(20), it means 20 bytes.</p></li>
<p>It shows all tables in the current DB. Note: wildcard character can be used in the table name to filter tables. Wildcard character: 1) ’%’ means 0 to any number of characters; 2)’_’ underscore means exactly one character.</p>
<p>It shows all tables in the current DB. Note: wildcard character can be used in the table name to filter tables. Wildcard character: 1) ’%’ means 0 to any number of characters; 2)’_’ underscore means exactly one character.</p></li>
<pre><codeclass='language-mysql'lang='mysql'>ALTER TABLE tb_name DROP COLUMN field_name
</code></pre>
<p>If the table is created via <ahref=''>Super Table</a>, the schema can only be changed via STable. But for tables not created from STable, you can change their schema directly.</p>
</li>
<pre><codeclass="mysql language-mysql">ALTER TABLE tb_name DROP COLUMN field_name </code></pre>
<p>If the table is created via [Super Table](), the schema can only be changed via STable. But for tables not created from STable, you can change their schema directly.</p></li>
</ul>
<p><strong>Tips</strong>: You can apply an operation on a table not in the current DB by concatenating DB name with the character '.', then with table name. For example, 'demo.tb1' means the operation is applied to table <code>tb1</code> in DB <code>demo</code> although <code>demo</code> is not the current selected DB. </p>
<p><strong>Tips</strong>: You can apply an operation on a table not in the current DB by concatenating DB name with the character '.', then with table name. For example, 'demo.tb1' means the operation is applied to table <code>tb1</code> in DB <code>demo</code> although <code>demo</code> is not the current selected DB. </p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO tb_name VALUES (field_value, ...);
</code></pre>
<p>Insert a data record into table tb_name</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">INSERT INTO tb_name VALUES (field_value, ...);</code></pre>
<p>Insert a data record into table tb_name</p></li>
<li><p><strong>Insert a Record with Selected Columns</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO tb_name (field1_name, ...) VALUES(field1_value, ...)
</code></pre>
<p>Insert a data record into table tb_name, with data in selected columns. If a column is not selected, the system will put NULL there. First column (time stamp ) could not be null, it must be there.</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">INSERT INTO tb_name (field1_name, ...) VALUES(field1_value, ...)</code></pre>
<p>Insert a data record into table tb_name, with data in selected columns. If a column is not selected, the system will put NULL there. First column (time stamp ) cant not be null, it must be inserted.</p></li>
<li><p><strong>Insert a Batch of Records</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...)...;
</code></pre>
<p>Insert multiple data records to the table</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...)...;</code></pre>
<p>Insert multiple data records to the table</p></li>
<li><p><strong>Insert a Batch of Records with Selected Columns</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO tb_name (field1_name, ...) VALUES(field1_value1, ...) (field1_value2, ...)
</code></pre>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">INSERT INTO tb_name (field1_name, ...) VALUES(field1_value1, ...) (field1_value2, ...)</code></pre></li>
<li><p><strong>Insert Records into Multiple Tables</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...)...
<p>Note: For a table, the new record must have timestamp bigger than the last data record, otherwise, it will be thrown away. If timestamp is 0, the time stamp will be set to the system time on server.</p>
<p><strong>IMPORT</strong>: If you do want to insert a historical data record into a table, use IMPORT command instead of INSERT. IMPORT has the same syntax as INSERT. If you want to import a batch of historical records, the records shall be ordered in the timestamp, otherwise, TDengine won't handle it in the right way.</p>
<p><strong>IMPORT</strong>: If you do want to insert a historical data record into a table, use IMPORT command instead of INSERT. IMPORT has the same syntax as INSERT. If you want to import a batch of historical records, the records shall be ordered in the timestamp, otherwise, TDengine won't handle it in the right way.</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT {* | expr_list} FROM tb_name
<pre><codeclass="mysql language-mysql">SELECT {* | expr_list} FROM tb_name
[WHERE where_condition]
[ORDER BY _c0 { DESC | ASC }]
[LIMIT limit [, OFFSET offset]]
...
...
@@ -161,205 +160,209 @@
SELECT function_list FROM tb_name
[WHERE where_condition]
[LIMIT limit [, OFFSET offset]]
[>> export_file]
</code></pre>
[>> export_file]</code></pre>
<ul>
<li>To query a table, use <code>*</code> to select all data from a table; or a specified list of expressions <code>expr_list</code> of columns. The SQL expression can contain alias and arithmetic operations between numeric typed columns.</li>
<li>For the <code>WHERE</code> conditions, use logical operations to filter the timestamp column and all numeric columns, and wild cards to filter the two string typed columns. </li>
<li>Sort the result set by the first column timestamp <code>_c0</code> (or directly use the timestamp column name) in either descending or ascending order (by default). "Order by" could not be applied to other columns.</li>
<li>Use <code>LIMIT</code> and <code>OFFSET</code> to control the number of rows returned and the starting position of the retrieved rows. LIMIT/OFFSET is applied after "order by" operations.</li>
<li>Export the retrieved result set into a CSV file using <code>>></code>. The target file's full path should be explicitly specified in the statement.</li>
<li>Sort the result set by the first column timestamp <code>_c0</code> (or directly use the timestamp column name) in either descending or ascending order (by default). "Order by" could not be applied to other columns.</li>
<li>Use <code>LIMIT</code> and <code>OFFSET</code> to control the number of rows returned and the starting position of the retrieved rows. LIMIT/OFFSET is applied after "order by" operations.</li>
<li>Export the retrieved result set into a CSV file using <code>>></code>. The target file's full path should be explicitly specified in the statement.</li>
</ul>
<aclass='anchor'id='Supported-Operations-of-Data-Filtering:'></a><h3>Supported Operations of Data Filtering:</h3>
<figure><figure><table>
<figure><table>
<thead>
<tr><th>Operation</th><th>Note</th><th>Applicable Data Types</th></tr></thead>
<tbody><tr><td>></td><td>larger than</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td><</td><td>smaller than</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td>>=</td><td>larger than or equal to</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td><=</td><td>smaller than or equal to</td><td><strong><code>timestamp</code></strong> and all numeric types</td></tr><tr><td>=</td><td>equal to</td><td>all types</td></tr><tr><td><></td><td>not equal to</td><td>all types</td></tr><tr><td>%</td><td>match with any char sequences</td><td><strong><code>binary</code></strong><strong><code>nchar</code></strong></td></tr><tr><td>_</td><td>match with a single char</td><td><strong><code>binary</code></strong><strong><code>nchar</code></strong></td></tr></tbody>
</table></figure></figure>
<tr>
<th>Operation</th>
<th>Note</th>
<th>Applicable Data Types</th>
</tr>
</thead>
<tbody>
<tr>
<td>></td>
<td>larger than</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td><</td>
<td>smaller than</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td>>=</td>
<td>larger than or equal to</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
</tr>
<tr>
<td><=</td>
<td>smaller than or equal to</td>
<td><strong><code>timestamp</code></strong> and all numeric types</td>
<li>For two or more conditions, only AND is supported, OR is not supported yet.</li>
<li>For filtering, only a single range is supported. For example, <code>value>20 and value<30</code> is valid condition, but <code>value<20 AND value<>5</code> is invalid condition</li>
<li><p>Query all the records in tb1 in the last hour:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT * FROM tb1 WHERE ts >= NOW - 1h
</code></pre>
</li>
</ul>
<ul>
<li><p>Query all the records in tb1 between 2018-06-01 08:00:00.000 and 2018-06-02 08:00:00.000, and filter out only the records whose col3 value ends with 'nny', and sort the records by their timestamp in a descending order:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT * FROM tb1 WHERE ts >'2018-06-01 08:00:00.000' AND ts <= '2018-06-02 08:00:00.000' AND col3 LIKE '%nny' ORDER BY ts DESC
</code></pre>
</li>
</ul>
<ul>
<li><p>Query the sum of col1 and col2 as alias 'complex_metric', and filter on the timestamp and col2 values. Limit the number of returned rows to 10, and offset the result by 5.</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT (col1 + col2) AS 'complex_metric' FROM tb1 WHERE ts >'2018-06-01 08:00:00.000' and col2 > 1.2 LIMIT 10 OFFSET 5
</code></pre>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT * FROM tb1 WHERE ts >= NOW - 1h</code></pre></li>
<li><p>Query all the records in tb1 between 2018-06-01 08:00:00.000 and 2018-06-02 08:00:00.000, and filter out only the records whose col3 value ends with 'nny', and sort the records by their timestamp in a descending order:</p>
<pre><codeclass="mysql language-mysql">SELECT * FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' AND ts <= '2018-06-02 08:00:00.000' AND col3 LIKE '%nny' ORDER BY ts DESC</code></pre></li>
<li><p>Query the sum of col1 and col2 as alias 'complex_metric', and filter on the timestamp and col2 values. Limit the number of returned rows to 10, and offset the result by 5.</p>
<pre><codeclass="mysql language-mysql">SELECT (col1 + col2) AS 'complex_metric' FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' and col2 > 1.2 LIMIT 10 OFFSET 5</code></pre></li>
<li><p>Query the number of records in tb1 in the last 10 minutes, whose col2 value is larger than 3.14, and export the result to file <code>/home/testoutpu.csv</code>.</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*) FROM tb1 WHERE ts >= NOW - 10m AND col2 > 3.14 >> /home/testoutpu.csv
</code></pre>
</li>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*) FROM tb1 WHERE ts >= NOW - 10m AND col2 > 3.14 >> /home/testoutpu.csv</code></pre></li>
<p>TDengine supports aggregations over numerical values, they are listed below:</p>
<ul>
<li><p><strong>COUNT</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]
</code></pre>
<p>Function: return the number of rows.<br/>Return Data Type: integer.<br/>Applicable Data Types: all.<br/>Applied to: table/STable.<br/>Note: 1) * can be used for all columns, as long as a column has non-NULL value, it will be counted; 2) If it is on a specific column, only rows with non-NULL value will be counted </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT COUNT([*|field_name]) FROM tb_name [WHERE clause]</code></pre>
<p>Function: return the number of rows.<br/>
Return Data Type: integer.<br/>
Applicable Data Types: all.<br/>
Applied to: table/STable.<br/>
Note: 1) * can be used for all columns, as long as a column has non-NULL value, it will be counted; 2) If it is on a specific column, only rows with non-NULL value will be counted </p></li>
<li><p><strong>AVG</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT AVG(field_name) FROM tb_name [WHERE clause]
</code></pre>
<p>Function: return the average value of a specific column.<br/>Return Data Type: double.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable. </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT AVG(field_name) FROM tb_name [WHERE clause]</code></pre>
<p>Function: return the average value of a specific column.<br/>
Return Data Type: double.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table/STable. </p></li>
<li><p><strong>WAVG</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT WAVG(field_name) FROM tb_name WHERE clause
</code></pre>
<p>Function: return the time-weighted average value of a specific column<br/>Return Data Type: double<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool<br/>Applied to: table/STable</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT WAVG(field_name) FROM tb_name WHERE clause</code></pre>
<p>Function: return the time-weighted average value of a specific column<br/>
Return Data Type: double<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool<br/>
Applied to: table/STable</p></li>
<li><p><strong>SUM</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT SUM(field_name) FROM tb_name [WHERE clause]
</code></pre>
<p>Function: return the sum of a specific column.<br/>Return Data Type: long integer or double.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable. </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT SUM(field_name) FROM tb_name [WHERE clause]</code></pre>
<p>Function: return the sum of a specific column.<br/>
Return Data Type: long integer or double.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table/STable. </p></li>
<li><p><strong>STDDEV</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT STDDEV(field_name) FROM tb_name [WHERE clause]
</code></pre>
<p>Function: return the standard deviation of a specific column.<br/>Return Data Type: double.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table. </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT STDDEV(field_name) FROM tb_name [WHERE clause]</code></pre>
<p>Function: return the standard deviation of a specific column.<br/>
Return Data Type: double.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table. </p></li>
<li><p><strong>LEASTSQUARES</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT LEASTSQUARES(field_name) FROM tb_name [WHERE clause]
</code></pre>
<pre><codeclass="mysql language-mysql">SELECT LEASTSQUARES(field_name) FROM tb_name [WHERE clause]</code></pre>
<p>Function: performs a linear fit to the primary timestamp and the specified column.
Return Data Type: return a string of the coefficient and the interception of the fitted line.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table.<br/>Note: The timestmap is taken as the independent variable while the specified column value is taken as the dependent variables.</p>
</li>
Return Data Type: return a string of the coefficient and the interception of the fitted line.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table.<br/>
Note: The timestmap is taken as the independent variable while the specified column value is taken as the dependent variables.</p></li>
<pre><codeclass='language-mysql'lang='mysql'>SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]
</code></pre>
<p>Function: return the minimum value of a specific column.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable. </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]</code></pre>
<p>Function: return the minimum value of a specific column.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table/STable. </p></li>
<li><p><strong>MAX</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]
</code></pre>
<p>Function: return the maximum value of a specific column.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable. </p>
<p>Function: return the maximum value of a specific column.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table/STable. </p></li>
<li><p><strong>FIRST</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT FIRST(field_name) FROM { tb_name | stb_name } [WHERE clause]
</code></pre>
<p>Function: return the first non-NULL value.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types.<br/>Applied to: table/STable.<br/>Note: To return all columns, use first(*). </p>
<p>Function: return the first non-NULL value.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types.<br/>
Applied to: table/STable.<br/>
Note: To return all columns, use first(*). </p></li>
<li><p><strong>LAST</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT LAST(field_name) FROM { tb_name | stb_name } [WHERE clause]
</code></pre>
<p>Function: return the last non-NULL value.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types.<br/>Applied to: table/STable.<br/>Note: To return all columns, use last(*). </p>
<p>Function: return the <code>k</code> largest values.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable.<br/>Note: 1) valid range of K: 1≤<em>k</em>≤100; 2) the associated time stamp will be returned too. </p>
<p>Function: return the <code>k</code> smallest values.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable.<br/>Note: 1) valid range of K: 1≤<em>k</em>≤100; 2) the associated timestamp will be returned too. </p>
<p>Function: the value of the specified column below which <code>P</code> percent of the data points fall.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable.<br/>Note: The range of <code>P</code> is <code>[0, 100]</code>. When <code>P=0</code> , <code>PERCENTILE</code> returns the equal value as <code>MIN</code>; when <code>P=100</code>, <code>PERCENTILE</code> returns the equal value as <code>MAX</code>. </p>
<p>Function: the value of the specified column below which <code>P</code> percent of the data points fall.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table/STable.<br/>
Note: The range of <code>P</code> is <code>[0, 100]</code>. When <code>P=0</code> , <code>PERCENTILE</code> returns the equal value as <code>MIN</code>; when <code>P=100</code>, <code>PERCENTILE</code> returns the equal value as <code>MAX</code>. </p></li>
<li><p><strong>LAST_ROW</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT LAST_ROW(field_name) FROM { tb_name | stb_name }
</code></pre>
<p>Function: return the last row.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types.<br/>Applied to: table/STable.<br/>Note: different from last, last_row returns the last row even it has NULL value. </p>
</li>
<pre><codeclass="mysql language-mysql">SELECT LAST_ROW(field_name) FROM { tb_name | stb_name } </code></pre>
<p>Function: return the last row.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types.<br/>
Applied to: table/STable.<br/>
Note: different from last, last_row returns the last row even it has NULL value. </p></li>
<pre><codeclass='language-mysql'lang='mysql'>SELECT DIFF(field_name) FROM tb_name [WHERE clause]
</code></pre>
<p>Function: return the difference between successive values of the specified column.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table. </p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT DIFF(field_name) FROM tb_name [WHERE clause]</code></pre>
<p>Function: return the difference between successive values of the specified column.<br/>
Return Data Type: the same data type.<br/>
Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>
Applied to: table. </p></li>
<li><p><strong>SPREAD</strong></p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]
</code></pre>
<p>Function: return the difference between the maximum and the mimimum value.<br/>Return Data Type: the same data type.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable.<br/>Note: spread gives the range of data variation in a table/supertable; it is equivalent to <code>MAX()</code> - <code>MIN()</code></p>
<p>Function: arithmetic operations on the selected columns.<br/>Return Data Type: double.<br/>Applicable Data Types: all types except timestamp, binary, nchar, bool.<br/>Applied to: table/STable.<br/>Note: 1) bracket can be used for operation priority; 2) If a column has NULL value, the result is NULL. </p>
<p>Time-series data are usually sampled by sensors at a very high frequency, but more often we are only interested in the downsampled, aggregated data of each timeline. TDengine provides a convenient way to downsample the highly frequently sampled data points as well as filling the missing data with a variety of interpolation choices.</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT function_list FROM tb_name
<pre><codeclass="mysql language-mysql">SELECT function_list FROM tb_name
[WHERE where_condition]
INTERVAL (interval)
[FILL ({NONE | VALUE | PREV | NULL | LINEAR})]
...
...
@@ -368,54 +371,53 @@ SELECT function_list FROM stb_name
[WHERE where_condition]
[GROUP BY tags]
INTERVAL (interval)
[FILL ({ VALUE | PREV | NULL | LINEAR})]
</code></pre>
[FILL ({ VALUE | PREV | NULL | LINEAR})]</code></pre>
<p>The downsampling time window is defined by <code>interval</code>, which is at least 10 milliseconds. The query returns a new series of downsampled data that has a series of fixed timestamps with an increment of <code>interval</code>. </p>
<p>For the time being, only function count, avg, sum, stddev, leastsquares, percentile, min, max, first, last are supported. Functions that may return multiple rows are not supported. </p>
<p>You can also use <code>FILL</code> to interpolate the intervals that don't contain any data.<code>FILL</code> currently supports four different interpolation strategies which are listed below:</p>
<figure><figure><table>
<p>You can also use <code>FILL</code> to interpolate the intervals that don't contain any data.<code>FILL</code> currently supports four different interpolation strategies which are listed below:</p>
<tbody><tr><td><code>FILL(VALUE, val1 [, val2, ...])</code></td><td>Interpolate with specified constants</td></tr><tr><td><code>FILL(PREV)</code></td><td>Interpolate with the value at the previous timestamp</td></tr><tr><td><code>FILL(LINEAR)</code></td><td>Linear interpolation with the non-null values at the previous timestamp and at the next timestamp</td></tr><tr><td><code>FILL(NULL)</code></td><td>Interpolate with <strong><code>NULL</code></strong> value</td></tr></tbody>
<td>Interpolate with the value at the previous timestamp</td>
</tr>
<tr>
<td><code>FILL(LINEAR)</code></td>
<td>Linear interpolation with the non-null values at the previous timestamp and at the next timestamp</td>
</tr>
<tr>
<td><code>FILL(NULL)</code></td>
<td>Interpolate with <strong><code>NULL</code></strong> value</td>
</tr>
</tbody>
</table></figure>
<p>A few downsampling examples:</p>
<ul>
<li><p>Find the number of data points, the maximum value of <code>col1</code> and minimum value of <code>col2</code> in a tb1 for every 10 minutes in the last 5 hours:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL (10m)
</code></pre>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL (10m)</code></pre></li>
<li><p>Fill the above downsampling results using constant-value interpolation:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(VALUE, 0, 1, -1)
</code></pre>
<p>Note that the number of constant values in <code>FILL()</code> should be equal or fewer than the number of functions in the <code>SELECT</code> clause. Exceeding fill constants will be ignored.</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(VALUE, 0, 1, -1)</code></pre>
<p>Note that the number of constant values in <code>FILL()</code> should be equal or fewer than the number of functions in the <code>SELECT</code> clause. Exceeding fill constants will be ignored.</p></li>
<li><p>Fill the above downsampling results using <code>PREV</code> interpolation:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(PREV)
</code></pre>
<p>This will interpolate missing data points with the value at the previous timestamp.</p>
</li>
</ul>
<ul>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(PREV)</code></pre>
<p>This will interpolate missing data points with the value at the previous timestamp.</p></li>
<li><p>Fill the above downsampling results using <code>NULL</code> interpolation:</p>
<pre><codeclass='language-mysql'lang='mysql'>SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(NULL)
</code></pre>
<p>Fill <strong><code>NULL</code></strong> to the interpolated data points.</p>
</li>
<pre><codeclass="mysql language-mysql">SELECT COUNT(*), MAX(col1), MIN(col2) FROM tb1 WHERE ts > NOW - 5h INTERVAL(10m) FILL(NULL)</code></pre>
<p>Fill <strong><code>NULL</code></strong> to the interpolated data points.</p></li>
</ul>
<p>Notes:</p>
<ol>
<li><code>FILL</code> can generate tons of interpolated data points if the interval is small and the queried time range is large. So always remember to specify a time range when using interpolation. For each query with interpolation, the result set can not exceed 10,000,000 records.</li>
<li>The result set will always be sorted by time in ascending order.</li>
<li>If the query object is a supertable, then all the functions will be applied to all the tables that qualify the <code>WHERE</code> conditions. If the <code>GROUP BY</code> clause is also applied, the result set will be sorted ascendingly by time in each single group, otherwise, the result set will be sorted ascendingly by time as a whole.</li>
* Fetches all results from an async query. It is preferable to use cursor.query_a() to create
* async queries and execute them instead of using the cursor object directly.
* @param {Object} options - An options object containing options for this function
* @param {function} callback - callback function that is callbacked on the COMPLETE fetched data (it is calledback only once!).
* Must be of form function (param, result, rowCount, rowData)
* @param {Object} param - A parameter that is also passed to the main callback function. Important! Param must be an object, and the key "data" cannot be used
* @return {{param:Object, result:buffer}} An object with the passed parameters object and the buffer instance that is a pointer to the result handle.
You can also query by binding parameters to a query by filling in the question marks in a string as so. The query will automatically parse what was binded and convert it to the proper format for use with TDengine
```javascript
varquery=cursor.query('select * from meterinfo.meters where ts <= ? and areaid = ?').bind(newDate(),5);
varquery=cursor.query('select * from meterinfo.meters where ts <= ? and areaid = ?;').bind(newDate(),5);
The TaosQuery object can also be immediately executed upon creation by passing true as the second argument, returning a promise instead of a TaosQuery.
```javascript
varpromise=cursor.query('select * from meterinfo.meters where v1 = 30',true)
varpromise=cursor.query('select * from meterinfo.meters where v1 = 30;',true)
If you want to execute queries without objects being wrapped around the data, use ```cursor.execute()``` directly and ```cursor.fetchall()``` to retrieve data if there is any.
```javascript
cursor.execute('select count(*), avg(v1), min(v2) from meterinfo.meters where ts >= \"2019-07-20 00:00:00.000\"');
cursor.execute('select count(*), avg(v1), min(v2) from meterinfo.meters where ts >= \"2019-07-20 00:00:00.000\";');
vardata=cursor.fetchall();
console.log(cursor.fields);// Latest query's Field metadata is stored in cursor.fields
console.log(cursor.data);// Latest query's result data is stored in cursor.data, also returned by fetchall.
...
...
@@ -130,7 +130,20 @@ console.log(cursor.data); // Latest query's result data is stored in cursor.data
### Async functionality
Coming soon
Async queries can be performed using the same functions such as `cursor.execute`, `cursor.query`, but now with `_a` appended to them.
Say you want to execute an two async query on two seperate tables, using `cursor.query_a`, you can do that and get a TaosQuery object, which upon executing with the `execute_a` function, returns a promise that resolves with a TaosResult object.
```javascript
varpromise1=cursor.query_a('select count(*), avg(v1), avg(v2) from meter1;').execute_a()
varpromise2=cursor.query_a('select count(*), avg(v1), avg(v2) from meter2;').execute_a();