Question

I'm using 6 tables for sensor measurement.

DEVICES
id imei        name
1  123456789   device1

BMP085
id deviceId date        time     pressure altitude tempC tempF
1  1        2014-02-21  20:01:02 000.00   000.00   00.00 00.00

GPS
id deviceId date       time     latitude longitude timeUtc  timeFix  altitude eps   epx   epv   ept   speed climb track mode satellites
1  1        2014-02-21 20:01:02 0.000000 0.000000  00:00:00 00:00:00 0.00     0.000 0.000 0.000 0.000 0.000 0.000 0.00  0    0

HIH6130
id deviceId date       time     humidity tempC tempF
1  1        2014-02-21 20:01:02 00.00    00.00 00.00

MINIMU9V2
id deviceId date        time    heading tempC tempF xAngle yAngle zAngle xAccel yAccel zAccel xMagn  yMagn  zMagn
1  1        2014-02-21 20:01:02 000.00  00.00 00.00 00.000 00.000 00.000 00.000 00.000 00.000 00.000 00.000 00.000

RASPI
id deviceId date       time     tempC tempF
1  1        2014-02-21 20:01:02 00.00 00.00

I would like to select all matching datasets of tables BMP085, GPS, HIH6130, MINIMU9V2 and RASPI that have the deviceId = 1. Only datasets fot this device are supposed to show up. Furthermore I'd like to select all matching datasets of tables BMP085, GPS, HIH6130, MINIMU9V2 and RASPI that have a date = 2014-02-21 and time >= 20:01:00 AND <= 20:01:30.

My current SQL statement looks like this:

SELECT t1.imei, t1.name, 
    t2.date, t2.time, t2.pressure, t2.altitude, t2.tempC, t2.tempF,
    t3.latitude, t3.longitude, t3.timeUtc, t3.timeFix, t3.altitude, t3.eps, t3.epx, t3.epv, t3.ept, t3.speed, t3.climb, t3.track, t3.mode, t3.satellites,
    t4.humidity, t4.tempC, t4.tempF,
    t5.heading, t5.tempC, t5.tempF, t5.xAngle, t5.yAngle, t5.zAngle, t5.xAccel, t5.yAccel, t5.zAccel, t5.xMagn, t5.yMagn, t5.zMagn,
    t6.tempC, t6.tempF
    FROM hab_DEVICES t1
    LEFT JOIN hab_BMP085 t2 ON t1.id = t2.deviceId
    LEFT JOIN hab_GPS t3 ON t1.id = t3.deviceId
    LEFT JOIN hab_HIH6130 t4 ON t1.id = t4.deviceId
    LEFT JOIN hab_MINIMU9V2 t5 ON t1.id = t5.deviceId
    LEFT JOIN hab_RASPI t6 ON t1.id = t6.deviceId       
    WHERE t1.id = 1
    AND t2.date = '2014-02-21'
    AND t2.date = t3.date
    AND t2.date = t4.date
    AND t2.date = t5.date
    AND t2.date = t6.date
    AND t2.time >= '20:01:00'
    AND t2.time <= '20:01:30'
    AND t2.time = t3.time
    AND t2.time = t4.time
    AND t2.time = t5.time
    AND t2.time = t6.time

The result is wrong as it displays multiple results for one given point in time instead of one single result. Furthermore the performance is quite bad as well.

Here is my fiddle: http://sqlfiddle.com/#!2/639c05/1/0

Any help is greatly appreciated.

Was it helpful?

Solution

Are you sure your dataset results are wrong? As you're joining a lot of tables, more than probably you have results duplicated in your tables, that make your rows shows up more than once.

For checking it:

SELECT t1.imei, t1.name, 
       t2.date, t2.time, t2.pressure, t2.altitude, t2.tempC, t2.tempF
FROM hab_DEVICES t1
LEFT JOIN hab_BMP085 t2 ON ( t1.id = t2.deviceId AND t1.id = 1 )
WHERE   t2.date = '2014-02-21'
    AND t2.time >= '20:01:00'
    AND t2.time <= '20:01:30'

And write down the number of rows you get (maybe you'll find useful for this using SELECT count(1) AS total instead of the fields, that will give you the number directly, ;D). When done, add other table and repeat. At the end you'll see what table is the responsible of duplicating your data. When you got that, you'll be able of know what you should do to correct it.

About the performance, LEFT JOIN is quite slow, if you could use INNER JOIN, you'd get quickly your results. You should also check for the indexes your tables have.

UPDATE

Ok, I found the problem: Your JOIN key is not only the id, it's also the time! If you only join by id, all the tables are going to multiply the selected values, but if you join by id, date and time, you retrieve the correct rows. Modify your SQL to be:

SELECT t1.imei, t1.name, 
        t2.date, t2.time, t2.pressure, t2.altitude, t2.tempC, t2.tempF,
        t3.latitude, t3.longitude, t3.timeUtc, t3.timeFix, t3.altitude, t3.eps, t3.epx, t3.epv, t3.ept, t3.speed, t3.climb, t3.track, t3.mode, t3.satellites,
        t4.humidity, t4.tempC, t4.tempF,
        t5.heading, t5.tempC, t5.tempF, t5.xAngle, t5.yAngle, t5.zAngle, t5.xAccel, t5.yAccel, t5.zAccel, t5.xMagn, t5.yMagn, t5.zMagn,
        t6.tempC, t6.tempF
        FROM hab_DEVICES t1
INNER JOIN hab_BMP085 t2 
ON (t1.id = t2.deviceId AND t1.id = 1 )
INNER JOIN hab_GPS t3
ON (t1.id = t3.deviceId AND t2.date = t3.date AND t2.time = t3.time AND t1.id = 1)
INNER JOIN hab_HIH6130 t4
ON (t1.id = t4.deviceId AND t2.date = t4.date AND t2.time = t4.time AND t1.id = 1)
INNER JOIN hab_MINIMU9V2 t5
ON (t1.id = t5.deviceId AND t2.date = t5.date AND t2.time = t5.time AND t1.id = 1)
INNER JOIN hab_RASPI t6
ON (t1.id = t6.deviceId AND t2.date = t6.date AND t2.time = t6.time AND t1.id = 1)  
WHERE t2.date = '2014-02-21'
AND t2.time >= '20:01:00'
AND t2.time <= '20:01:30'

Check this Fiddle: http://sqlfiddle.com/#!2/639c05/24

I assumed as "master time" the time in table 2, but you may use whatever makes more sense to you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top