Query to combine multiple hypertables of sensor values

I have multiple tables with a Unix timestamp and a sensor reading/value. The sensors are all of the same data type(float). I am trying to figure out a query that combines all of the sensor readings into a single result table. The different sensors can record a value a different times.

example sensor data tables:

Sensor data tables

tstamp Sensor_01
1740808800 800.7
1740808805 801.1
1740808810 801.5
1740808815 800.6
tstamp Sensor_02
1740808800 804.3
1740808803 805.0
1740808810 805.5
1740808816 803.9
tstamp Sensor_03
1740808801 810.2
1740808805 810.4
1740808807 810.9
1740808816 810.0

What query would I use to produce the table below from the input tables above? NULL values in the sensor columns are okay. I’ve tried multiple JOIN queries, but haven’t gotten it to work yet. Thanks for any suggestions.

tstamp Sensor_01 Sensor_02 Sensor_03
1740808800 800.7 804.3 NULL
1740808801 NULL NULL 810.2
1740808803 NULL 805.0 NULL
1740808805 801.1 NULL 810.4
1740808807 NULL NULL 810.9
1740808810 801.5 805.5 NULL
1740808815 800.6 NULL NULL
1740808816 NULL 803.9 810.0

Hello @lsossai, the secret sauce here is mix coalesce with full outer join.

-- Query to combine all sensor readings, showing NULLs when a sensor doesn't have a reading
SELECT 
    COALESCE(s1.time, s2.time, s3.time) AS tstamp,
    s1.value AS sensor_1,
    s2.value AS sensor_2,
    s3.value AS sensor_3
FROM 
    sensor_1 s1
    FULL OUTER JOIN sensor_2 s2 ON s1.time = s2.time
    FULL OUTER JOIN sensor_3 s3 ON COALESCE(s1.time, s2.time) = s3.time
ORDER BY 
    tstamp;

Here’s a complete example:

create table sensor_1 (
    time timestamp not null,
    value float not null
);

create table sensor_2 (
    time timestamp not null,
    value float not null
);

create table sensor_3 (
    time timestamp not null,
    value float not null
);

select create_hypertable('sensor_1', 'time'),
 create_hypertable('sensor_2', 'time'), 
 create_hypertable('sensor_3', 'time');

insert into sensor_1 (time, value) values (now(), 1.0), (now() - interval '1 day', 2.0), (now() - interval '2 day', 3.0);
insert into sensor_2 (time, value) values (now(), 4.0), (now() - interval '1 day', 5.0), (now() - interval '2 day', 6.0);
insert into sensor_3 (time, value) values (now(), 7.0), (now() - interval '1 day', 8.0), (now() - interval '2 day', 9.0);

-- Query to combine all sensor readings, showing NULLs when a sensor doesn't have a reading
SELECT 
    COALESCE(s1.time, s2.time, s3.time) AS tstamp,
    s1.value AS sensor_1,
    s2.value AS sensor_2,
    s3.value AS sensor_3
FROM 
    sensor_1 s1
    FULL OUTER JOIN sensor_2 s2 ON s1.time = s2.time
    FULL OUTER JOIN sensor_3 s3 ON COALESCE(s1.time, s2.time) = s3.time
ORDER BY 
    tstamp;

-- Example for combining data from separate sensor tables (using existing schema)
-- Our tables are structured as: sensor_X(time timestamp, value float)

SELECT 
    COALESCE(s1.time, s2.time, s3.time) AS tstamp,
    s1.value AS Sensor_01,
    s2.value AS Sensor_02,
    s3.value AS Sensor_03
FROM 
    sensor_1 s1
    FULL OUTER JOIN sensor_2 s2 ON s1.time = s2.time
    FULL OUTER JOIN sensor_3 s3 ON COALESCE(s1.time, s2.time) = s3.time
ORDER BY 
    tstamp;

-- Using time_bucket to group readings into 5-second intervals
-- This query groups timestamp data into buckets

-- A cleaner approach using FULL OUTER JOIN with time_bucket
WITH 
    sensor_1_bucketed AS (
        SELECT time_bucket('5 seconds', time) AS bucket_time, value
        FROM sensor_1
    ),
    sensor_2_bucketed AS (
        SELECT time_bucket('5 seconds', time) AS bucket_time, value
        FROM sensor_2
    ),
    sensor_3_bucketed AS (
        SELECT time_bucket('5 seconds', time) AS bucket_time, value
        FROM sensor_3
    )
SELECT 
    COALESCE(s1.bucket_time, s2.bucket_time, s3.bucket_time) AS tstamp,
    s1.value AS Sensor_01,
    s2.value AS Sensor_02,
    s3.value AS Sensor_03
FROM 
    sensor_1_bucketed s1
    FULL OUTER JOIN sensor_2_bucketed s2 ON s1.bucket_time = s2.bucket_time
    FULL OUTER JOIN sensor_3_bucketed s3 ON COALESCE(s1.bucket_time, s2.bucket_time) = s3.bucket_time
ORDER BY 
    tstamp;

Thanks for the suggestions jonatasdp. I stumbled upon the coalesce and FULL OUTER JOIN method after my original post, when I was doing some more reading online. Your solutions are slightly different from what I found, and gave me some more things to try out.