06-select.md 17.9 KB
Newer Older
1 2
---
title: Select
D
danielclow 已提交
3 4
sidebar_label: Select
description: This document describes how to query data in TDengine.
5 6 7 8
---

## Syntax

9
```sql
10
SELECT {DATABASE() | CLIENT_VERSION() | SERVER_VERSION() | SERVER_STATUS() | NOW() | TODAY() | TIMEZONE() | CURRENT_USER() | USER() }
11 12 13 14

SELECT [DISTINCT] select_list
    from_clause
    [WHERE condition]
D
dapan1121 已提交
15
    [partition_by_clause]
G
Ganlin Zhao 已提交
16
    [interp_clause]
17 18 19
    [window_clause]
    [group_by_clause]
    [order_by_clasue]
20 21
    [SLIMIT limit_val [SOFFSET offset_val]]
    [LIMIT limit_val [OFFSET offset_val]]
22
    [>> export_file]
23

24 25
select_list:
    select_expr [, select_expr] ...
26

27 28 29 30 31 32 33
select_expr: {
    *
  | query_name.*
  | [schema_name.] {table_name | view_name} .*
  | t_alias.*
  | expr [[AS] c_alias]
}
34

35 36 37 38 39 40 41 42 43 44 45 46 47
from_clause: {
    table_reference [, table_reference] ...
  | join_clause [, join_clause] ...
}

table_reference:
    table_expr t_alias

table_expr: {
    table_name
  | view_name
  | ( subquery )
}
48

49 50
join_clause:
    table_reference [INNER] JOIN table_reference ON condition
51

52 53 54 55 56
window_clause: {
    SESSION(ts_col, tol_val)
  | STATE_WINDOW(col)
  | INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [WATERMARK(watermark_val)] [FILL(fill_mod_and_val)]

57
interp_clause:
G
Ganlin Zhao 已提交
58
    RANGE(ts_val [, ts_val]) EVERY(every_val) FILL(fill_mod_and_val)
59

D
dapan1121 已提交
60
partition_by_clause:
61
    PARTITION BY expr [, expr] ...
D
dapan1121 已提交
62

63 64 65 66 67 68 69 70
group_by_clause:
    GROUP BY expr [, expr] ... HAVING condition

order_by_clasue:
    ORDER BY order_expr [, order_expr] ...

order_expr:
    {expr | position | c_alias} [DESC | ASC] [NULLS FIRST | NULLS LAST]
71
```
72 73 74 75 76

## Lists

A query can be performed on some or all columns. Data and tag columns can all be included in the SELECT list.

77
### Wildcards
78

W
wade zhang 已提交
79
You can use an asterisk (\*) as a wildcard character to indicate all columns. For normal tables or sub-tables, the asterisk indicates only data columns. For supertables, tag columns are also included when using asterisk (\*).
80 81 82

```sql
SELECT * FROM d1001;
83 84
```

85
You can use a table name as a prefix before an asterisk. For example, the following SQL statements both return all columns from the d1001 table:
86

87
```sql
88 89 90 91
SELECT * FROM d1001;
SELECT d1001.* FROM d1001;
```

92
However, in a JOIN query, using a table name prefix with an asterisk returns different results. In this case, querying * returns all data in all columns in all tables (not including tags), whereas using a table name prefix returns all data in all columns in the specified table only.
93

94 95 96
```sql
SELECT * FROM d1001, d1003 WHERE d1001.ts=d1003.ts;
SELECT d1001.* FROM d1001,d1003 WHERE d1001.ts = d1003.ts;
97 98
```

99
The first of the preceding SQL statements returns all columns from the d1001 and d1003 tables, but the second of the preceding SQL statements returns all columns from the d1001 table only.
100

101 102
With regard to the other SQL functions that support wildcards, the differences are as follows:
`count(*)` only returns one column. `first`, `last`, and `last_row` return all columns.
103

104
### Tag Columns
105

106 107 108 109
You can query tag columns in supertables and subtables and receive results in the same way as querying data columns.

```sql
SELECT location, groupid, current FROM d1001 LIMIT 2;
110 111
```

112
### Distinct Values
113

114
The DISTINCT keyword returns only values that are different over one or more columns. You can use the DISTINCT keyword with tag columns and data columns.
115

116
The following SQL statement returns distinct values from a tag column:
117

118 119 120
```sql
SELECT DISTINCT tag_name [, tag_name ...] FROM stb_name;
```
121

122
The following SQL statement returns distinct values from a data column:
123 124 125 126 127 128 129

```sql
SELECT DISTINCT col_name [, col_name ...] FROM tb_name;
```

:::info

130 131
1. Configuration parameter `maxNumOfDistinctRes` in `taos.cfg` is used to control the number of rows to output. The minimum configurable value is 100,000, the maximum configurable value is 100,000,000, the default value is 1,000,000. If the actual number of rows exceeds the value of this parameter, only the number of rows specified by this parameter will be output.
2. It can't be guaranteed that the results selected by using `DISTINCT` on columns of `FLOAT` or `DOUBLE` are exactly unique because of the precision errors in floating point numbers.
132 133 134

:::

135
### Column Names
136

137
When using `SELECT`, the column names in the result set will be the same as that in the select clause if `AS` is not used. `AS` can be used to rename the column names in the result set. For example:
138

139
```sql
140 141 142 143 144
taos> SELECT ts, ts AS primary_key_ts FROM d1001;
```

`AS` can't be used together with `first(*)`, `last(*)`, or `last_row(*)`.

145 146
### Pseudocolumns

147 148
**Pseudocolumn:** A pseudo-column behaves like a table column but is not actually stored in the table. You can select from pseudo-columns, but you cannot insert, update, or delete their values. A pseudo-column is also similar to a function without arguments. This section describes these pseudo-columns:

149 150
**TBNAME**
The TBNAME pseudocolumn in a supertable contains the names of subtables within the supertable.
151

152
The following SQL statement returns all unique subtable names and locations within the meters supertable:
153

154 155 156
```mysql
SELECT DISTINCT TBNAME, location FROM meters;
```
157

158
Use the `INS_TAGS` system table in `INFORMATION_SCHEMA` to query the information for subtables in a supertable. For example, the following statement returns the name and tag values for each subtable in the `meters` supertable.
159

160 161
```mysql
SELECT table_name, tag_name, tag_type, tag_value FROM information_schema.ins_tags WHERE stable_name='meters';
162 163
```

164
The following SQL statement returns the number of subtables within the meters supertable.
165

166 167
```mysql
SELECT COUNT(*) FROM (SELECT DISTINCT TBNAME FROM meters);
168 169
```

D
dapan1121 已提交
170
In the preceding two statements, only tags can be used as filtering conditions in the WHERE clause. 
171

172
**\_QSTART and \_QEND**
173

174
The \_QSTART and \_QEND pseudocolumns contain the beginning and end of the time range of a query. If the WHERE clause in a statement does not contain valid timestamps, the time range is equal to [-2^63, 2^63 - 1].
175

176
The \_QSTART and \_QEND pseudocolumns cannot be used in a WHERE clause.
177

S
Sean Ely 已提交
178 179
**\_WSTART, \_WEND, and \_WDURATION**

180
The \_WSTART, \_WEND, and \_WDURATION pseudocolumns indicate the beginning, end, and duration of a window.
181

182
These pseudocolumns can be used only in time window-based aggregations and must occur after the aggregation clause.
183

184
**\_c0 and \_ROWTS**
185

186 187 188 189
In TDengine, the first column of all tables must be a timestamp. This column is the primary key of the table. The \_c0 and \_ROWTS pseudocolumns both represent the values of this column. These pseudocolumns enable greater flexibility and standardization. For example, you can use functions such as MAX and MIN with these pseudocolumns.

```sql
select _rowts, max(current) from meters;
190 191
```

G
Ganlin Zhao 已提交
192 193
**\_IROWTS**

G
Ganlin Zhao 已提交
194
The \_IROWTS pseudocolumn can only be used with INTERP function. This pseudocolumn can be used to retrieve the corresponding timestamp column associated with the interpolation results.
G
Ganlin Zhao 已提交
195 196 197 198 199

```sql
select _irowts, interp(current) from meters range('2020-01-01 10:00:00', '2020-01-01 10:30:00') every(1s) fill(linear);
```

200
## Query Objects
201

202 203
`FROM` can be followed by a number of tables or super tables, or can be followed by a sub-query.
If no database is specified as current database in use, table names must be preceded with database name, for example, `power.d1001`.
204

205
You can perform INNER JOIN statements based on the primary key. The following conditions apply:
206

207 208 209 210 211
1. You can use FROM table list or an explicit JOIN clause.
2. For standard tables and subtables, you must specify an ON condition and the condition must be equivalent to the primary key.
3. For supertables, the ON condition must be equivalent to the primary key. In addition, the tag columns of the tables on which the INNER JOIN is performed must have a one-to-one relationship. You cannot specify an OR condition.
4. The tables that are included in a JOIN clause must be of the same type (supertable, standard table, or subtable).
5. You can include subqueries before and after the JOIN keyword.
D
dapan1121 已提交
212
6. You cannot include a FILL clause and a JOIN clause in the same statement.
213

214
## GROUP BY
215

216
If you use a GROUP BY clause, the SELECT list can only include the following items:
217

218 219 220 221
1. Constants
2. Aggregate functions
3. Expressions that are consistent with the expression following the GROUP BY clause
4. Expressions that include the preceding expression
222

223
The GROUP BY clause groups each row of data by the value of the expression following the clause and returns a combined result for each group.
224

225
The expressions in a GROUP BY clause can include any column in any table or view. It is not necessary that the expressions appear in the SELECT list.
226

227
The GROUP BY clause does not guarantee that the results are ordered. If you want to ensure that grouped data is ordered, use the ORDER BY clause.
228 229


230
## PARTITION BY
231

232
The PARTITION BY clause is a TDengine-specific extension to standard SQL. This clause partitions data based on the part_list and performs computations per partition.
233

234
For more information, see TDengine Extensions.
235

236
## ORDER BY
237

238
The ORDER BY keyword orders query results. If you do not include an ORDER BY clause in a query, the order of the results can be inconsistent.
239

240 241 242 243 244 245 246 247 248 249
You can specify integers after ORDER BY to indicate the order in which you want the items in the SELECT list to be displayed. For example, 1 indicates the first item in the select list.

You can specify ASC for ascending order or DESC for descending order.

You can also use the NULLS keyword to specify the position of null values. Ascending order uses NULLS LAST by default. Descending order uses NULLS FIRST by default.

## LIMIT

The LIMIT keyword controls the number of results that are displayed. You can also use the OFFSET keyword to specify the result to display first. `LIMIT` and `OFFSET` are executed after `ORDER BY` in the query execution. You can include an offset in a LIMIT clause. For example, LIMIT 5 OFFSET 2 can also be written LIMIT 2, 5. Both of these clauses display the third through the seventh results.

D
dapan1121 已提交
250
In a statement that includes a PARTITION BY/GROUP BY clause, the LIMIT keyword is performed on each partition/group, not on the entire set of results.
251 252 253

## SLIMIT

D
dapan1121 已提交
254
The SLIMIT keyword is used with a PARTITION BY/GROUP BY clause to control the number of partitions/groups that are displayed. You can include an offset in a SLIMIT clause. For example, SLIMIT 5 OFFSET 2 can also be written LIMIT 2, 5. Both of these clauses display the third through the seventh partitions/groups.
255

D
dapan1121 已提交
256
Note: If you include an ORDER BY clause, only one partition/group can be displayed.
257 258

## Special Query
259

260
Some special query functions can be invoked without `FROM` sub-clause.
261

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
262
### Obtain Current Database
263 264 265 266 267

The following SQL statement returns the current database. If a database has not been specified on login or with the `USE` command, a null value is returned.

```sql
SELECT DATABASE();
268 269
```

270
### Obtain Current Version
271

272 273 274
```sql
SELECT CLIENT_VERSION();
SELECT SERVER_VERSION();
275 276
```

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
277
### Obtain Server Status
278 279 280 281 282

The following SQL statement returns the status of the TDengine server. An integer indicates that the server is running normally. An error code indicates that an error has occurred. This statement can also detect whether a connection pool or third-party tool is connected to TDengine properly. By using this statement, you can ensure that connections in a pool are not lost due to an incorrect heartbeat detection statement.

```sql
SELECT SERVER_STATUS();
283 284
```

285
### Obtain Current Time
286

287 288 289
```sql
SELECT NOW();
```
290

291
### Obtain Current Date
292

293 294 295
```sql
SELECT TODAY();
```
296

297
### Obtain Current Time Zone
298

299 300 301
```sql
SELECT TIMEZONE();
```
302

303 304 305 306 307 308
### Obtain Current User

```sql
SELECT CURRENT_USER();
```

309 310 311 312
## Regular Expression

### Syntax

313
```txt
W
wade zhang 已提交
314
WHERE (column|tbname) match/MATCH/nmatch/NMATCH _regex_
315 316 317 318
```

### Specification

319
TDengine supports POSIX regular expression syntax. For more information, see [Regular Expressions](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html).
320 321 322

### Restrictions

323
Regular expression filtering is supported only on table names (TBNAME), BINARY tags, and NCHAR tags. Regular expression filtering cannot be performed on data columns.
324

325
A regular expression string cannot exceed 128 bytes. You can configure this value by modifying the maxRegexStringLen parameter on the TDengine Client. The modified value takes effect when the client is restarted.
326

X
Xiaoyu Wang 已提交
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
## CASE Expressions

### Syntax

```txt
CASE value WHEN compare_value THEN result [WHEN compare_value THEN result ...] [ELSE result] END
CASE WHEN condition THEN result [WHEN condition THEN result ...] [ELSE result] END
```

### Description
CASE expressions let you use IF ... THEN ... ELSE logic in SQL statements without having to invoke procedures. 

The first CASE syntax returns the `result` for the first `value`=`compare_value` comparison that is true. 

The second syntax returns the `result` for the first `condition` that is true. 

If no comparison or condition is true, the result after ELSE is returned, or NULL if there is no ELSE part.

The return type of the CASE expression is the result type of the first WHEN WHEN part, and the result type of the other WHEN WHEN parts and ELSE parts can be converted to them, otherwise TDengine will report an error.

347 348 349 350 351 352 353 354 355 356 357 358 359 360
### Examples

A device has three status codes to display its status. The statements are as follows:

```sql
SELECT CASE dev_status WHEN 1 THEN 'Running' WHEN 2 THEN 'Warning' WHEN 3 THEN 'Downtime' ELSE 'Unknown' END FROM dev_table;
```

The average voltage value of the smart meter is counted. When the voltage is less than 200 or more than 250, it is considered that the statistics is wrong, and the value is corrected to 220. The statement is as follows:

```sql
SELECT AVG(CASE WHEN voltage < 200 or voltage > 250 THEN 220 ELSE voltage END) FROM meters;
```

361 362
## JOIN

D
dapan1121 已提交
363
TDengine supports the `INTER JOIN` based on the timestamp primary key, that is, the `JOIN` condition must contain the timestamp primary key. As long as the requirement of timestamp-based primary key is met, `INTER JOIN` can be made between normal tables, sub-tables, super tables and sub-queries at will, and there is no limit on the number of tables, primary key and other conditions must be combined with `AND` operator.
364

365
For standard tables:
366 367 368 369 370 371 372

```sql
SELECT *
FROM temp_tb_1 t1, pressure_tb_1 t2
WHERE t1.ts = t2.ts
```

373
For supertables:
374 375 376

```sql
SELECT *
377
FROM temp_stable t1, temp_stable t2
378 379 380
WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0;
```

381
For sub-table and super table:
382

383 384 385 386 387
```sql
SELECT *
FROM temp_ctable t1, temp_stable t2
WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0;
```
388

389
Similarly, join operations can be performed on the result sets of multiple subqueries.
390 391 392

## Nested Query

393
Nested query is also called sub query. This means that in a single SQL statement the result of inner query can be used as the data source of the outer query.
394

S
Sean Ely 已提交
395
From 2.2.0.0, unassociated sub query can be used in the `FROM` clause. Unassociated means the sub query doesn't use the parameters in the parent query. More specifically, in the `tb_name_list` of `SELECT` statement, an independent SELECT statement can be used. So a complete nested query looks like:
396

397
```
398 399 400 401 402
SELECT ... FROM (SELECT ... FROM ...) ...;
```

:::info

G
gccgdb1234 已提交
403
- The result of a nested query is returned as a virtual table used by the outer query. It's recommended to give an alias to this table for the convenience of using it in the outer query.
404
- JOIN operation is allowed between tables/STables inside both inner and outer queries. Join operation can be performed on the result set of the inner query.
G
gccgdb1234 已提交
405
- The features that can be used in the inner query are the same as those that can be used in a non-nested query.
406 407
  - `ORDER BY` inside the inner query is unnecessary and will slow down the query performance significantly. It is best to avoid the use of `ORDER BY` inside the inner query.
- Compared to the non-nested query, the functionality that can be used in the outer query has the following restrictions:
408
  - Functions
G
gccgdb1234 已提交
409
    - If the result set returned by the inner query doesn't contain timestamp column, then functions relying on timestamp can't be used in the outer query, like INTERP,DERIVATIVE, IRATE, LAST_ROW, FIRST, LAST, TWA, STATEDURATION, TAIL, UNIQUE.
W
wade zhang 已提交
410
    - If the result set returned by the inner query are not sorted in order by timestamp, then functions relying on data ordered by timestamp can't be used in the outer query, like LEASTSQUARES, ELAPSED, INTERP, DERIVATIVE, IRATE, TWA, DIFF, STATECOUNT, STATEDURATION, CSUM, MAVG, TAIL, UNIQUE. 
G
gccgdb1234 已提交
411
    - Functions that need to scan the data twice can't be used in the outer query, like PERCENTILE.
412 413 414 415 416

:::

## UNION ALL

417
```txt title=Syntax
418 419 420 421 422
SELECT ...
UNION ALL SELECT ...
[UNION ALL SELECT ...]
```

423
TDengine supports the `UNION ALL` operation. `UNION ALL` operator can be used to combine the result set from multiple select statements as long as the result set of these select statements have exactly the same columns. `UNION ALL` doesn't remove redundant rows from multiple result sets. In a single SQL statement, at most 100 `UNION ALL` can be supported.
424 425 426 427 428

### Examples

table `tb1` is created using below SQL statement:

429
```
430 431 432 433 434
CREATE TABLE tb1 (ts TIMESTAMP, col1 INT, col2 FLOAT, col3 BINARY(50));
```

The rows in the past one hour in `tb1` can be selected using below SQL statement:

435
```
436 437 438 439 440
SELECT * FROM tb1 WHERE ts >= NOW - 1h;
```

The rows between 2018-06-01 08:00:00.000 and 2018-06-02 08:00:00.000 and col3 ends with 'nny' can be selected in the descending order of timestamp using below SQL statement:

441
```
442 443 444 445 446
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;
```

The sum of col1 and col2 for rows later than 2018-06-01 08:00:00.000 and whose col2 is bigger than 1.2 can be selected and renamed as "complex", while only 10 rows are output from the 5th row, by below SQL statement:

447
```
448 449 450
SELECT (col1 + col2) AS 'complex' FROM tb1 WHERE ts > '2018-06-01 08:00:00.000' AND col2 > 1.2 LIMIT 10 OFFSET 5;
```

451
The rows in the past 10 minutes and whose col2 is bigger than 3.14 are selected and output to the result file `/home/testoutput.csv` with below SQL statement:
452

453
```
454
SELECT COUNT(*) FROM tb1 WHERE ts >= NOW - 10m AND col2 > 3.14 >> /home/testoutput.csv;
455
```