You can use the SELECT
statement in PostgreSQL and TimescaleDB to retrieve data from zero or more tables in your database. It returns these results in a result table, called a result set, that consists of zero or more rows.
The SELECT
statement is one of the simplest and most complex SQL statements because you can use a lot of optional clauses and keywords with it. This complexity provides greater flexibility when you fetch data from a database.
SELECT
syntax:
Simple:
SELECT <expressions>
FROM <tables>;
Full:
SELECT [ ALL | DISTINCT | DISTINCT ON (<distinct_expressions>) ]
<expressions>
FROM <tables>
[WHERE <conditions>]
[GROUP BY <expressions>]
[HAVING <condition>]
[ORDER BY <expression> [ ASC | DESC | USING <operator> ] [ NULLS FIRST FIRST | NULLS LASTLAST ]]
[LIMIT [ <number_rows> | ALL]
[OFFSET OFFSET <offset_value> [ ROW | ROWS ]]
[FETCH FETCH { FIRST FIRST | NEXT } [ <fetch_rows> ] { ROW | ROWS } ONLY]
[FOR { UPDATE | SHARE } OF <table> [ NOWAIT ]];
This example uses a table called stock_data
, that contains data about the price of a stock over time:
id | time | group | price |
1 | 2022-06-04 | b | 251.12 |
3 | 2022-06-04 | a | 208.88 |
6 | 2022-06-04 | c | 82.70 |
2 | 2022-06-05 | a | 210.88 |
4 | 2022-06-05 | b | 362.67 |
5 | 2022-06-05 | b | 128.45 |
The simplest SELECT
query is to use an asterisk without a WHERE
clause. This will return every column from every record in the table. For example, this query returns every record from the example table:
SELECT * FROM stock_data;
While SELECT *
might work for ad-hoc queries on small tables to eyeball the data, it shouldn’t be used in production code. There, you should select only the data you need for performance and maintainability.
You can also select the results of an expression without including a table.
SELECT 6 * 3 AS result;
Results:
result |
18 |
If you want all the data from a single column, specify the name of the column in the SELECT
statement. For example, this query that retrieves all the data in the price
column prices from the stock_data
table:
SELECT price FROM stock_data;
Results:
price |
251.12 |
208.88 |
82.70 |
210.88 |
362.67 |
128.45 |
If you only want the data from specific columns in a table, you can specify the names of the columns in the SELECT
statement, separated by commas. For example:
SELECT time, price FROM stock_data;
Results:
time | price |
2022-06-04 | 251.12 |
2022-06-04 | 208.88 |
2022-06-04 | 82.70 |
2022-06-05 | 210.88 |
2022-06-05 | 362.67 |
2022-06-05 | 128.45 |
You can modify the results of your SELECT
statement by using an expression.
This example combines two of the columns in the example table into one. You can use the ||
operator to concatenate values in SQL. When you do this, you can add an alias to the generated column to make it easier to identify it in the results. For example, you can use a AS
clause to display the result as time_price
.
SELECT time || ':' || price AS time_price FROM stock_data;
Results:
time_price |
2022-06-04:251.12 |
2022-06-04:208.88 |
2022-06-04:82.70 |
2022-06-05:210.88 |
2022-06-05:362.67 |
2022-06-05:128.45 |
You can filter the records by adding a WHERE
clause with conditions. This example query returns time and group from the stock_data
table, if where the price is more than 200.
SELECT time, group, price from stock_data WHERE price > 200;
Results:
time | group | price |
2022-06-04 | b | 251.12 |
2022-06-04 | a | 208.88 |
2022-06-05 | a | 210.88 |
2022-06-05 | b | 362.67 |
When you retrieve data from a database, you can use ORDER BY
to change the order of the results with the ORDER BY
keyword. Here is an example:
SELECT * FROM stock_data ORDER BY price;
Result:
id | time | group | price |
6 | 2022-06-04 | c | 82.70 |
5 | 2022-06-05 | b | 128.45 |
3 | 2022-06-04 | a | 208.88 |
2 | 2022-06-05 | a | 210.88 |
1 | 2022-06-04 | b | 251.12 |
4 | 2022-06-05 | b | 362.67 |
If you don’t want duplicates in your results, you can add the DISTINCT
keyword to your SELECT
clause. For example, this query only retrieves the distinct groups from the stock_data
table, and removes the duplicates.
SELECT DISTINCT group from stock_data;
Result:
Group |
b |
a |
c |
This section uses an example table called conditions that contains information about temperature and humidity gathered from different devices in different locations:
time | device_id | temperature | humidity |
2016-11-15 07:00:00 | weather-pro-000000 | 32.4 | 49.8 |
2016-11-15 07:00:00 | weather-pro-000001 | 34.6 | 50.1 |
2016-11-15 07:00:00 | weather-pro-000002 | 73.8 | 74 |
2016-11-15 07:00:00 | weather-pro-000003 | 68.7 | 68 |
To calculate the average temperature of each device in the table, you can use a query like this:
SELECT device_id, AVG(temperature) FROM conditions GROUP BY device_id;
The GROUP BY
keyword groups the results by the device_id
, and the AVG()
function returns the average of each device’s temperature. The results of that query look a bit like this:
Results:
device_id | avg |
weather-pro-000000 | 39.3281 |
weather-pro-000001 | 38.4629 |
weather-pro-000002 | 80.3776 |
weather-pro-000003 | 68.4865 |
You can also find the highest humidity recorded by each device using the MAX()
function. For example:
SELECT device_id, MAX(humidity) FROM conditions GROUP BY device_id;
The results of the query look like this:
device_id | avg |
weather-pro-000000 | 55.5 |
weather-pro-000001 | 56 |
weather-pro-000002 | 55.2 |
weather-pro-000003 | 54.4 |
For more information on the SELECT
statement and how to use it with PostgreSQL, check out the PostgreSQL documentation on SELECT. For more examples of how you can use SELECT
in your SQL queries, see these Timescale documentation sections: