2013-06-21 204 views
2
SELECT 
    MAX(timestamp) as end, 
    MIN(timestamp) as start, 
    (MAX(odometerKM) - MIN(odometerKM)) as distanceTravelled, 
    (SELECT COUNT(*) FROM EventData WHERE speedKPH = 0 AND timestamp >= ? AND timestamp <= ? AND deviceID = ?) as stopsDuration, 
    (SELECT COUNT(*) FROM EventData WHERE speedKPH != 0 AND timestamp >= ? AND timestamp <= ? AND deviceID = ?) as tripDuration, 
    (MAX(odometerKM) - MIN(odometerKM))/(SELECT fuelEconomy FROM Device WHERE deviceID = ?) as fuelConsumption 
FROM EventData 
WHERE deviceID = ? AND timestamp >= ? AND timestamp <= ? 

非常令人困惑,但我创建了此查询来查找行集合的摘要。最小和最大时间戳很简单,但要找到速度为零而非零的行的COUNT,我做了一个丑陋的黑客。我相信有更好的方法来做到这一点?以更好的方式写这个SQL查询的好方法是什么?

更新:“?”请参阅由CodeIgniter的一个不成熟的查询生成器替换。可悲的是,它尚不支持命名参数。

+0

你没忘了,包括在条件'WHERE设备ID ='你前两个子查询? – RandomSeed

+0

@Yak:是的。让我编辑。 – Shubham

+0

此外,它看起来像相同的两个子查询实际上计算一个*号*的事件('COUNT()')而不是持续时间? – RandomSeed

回答

0

你应该包含DeviceID,所以它是有道理的。试试这个:

SELECT 
DeviceID, 
MAX(timestamp) as end, 
MIN(timestamp) as start, 
(MAX(odometerKM) - MIN(odometerKM)) as distanceTravelled, 
SUM (
    case speedKPH 
    when 0 then 1 
    else 0 
    end) as stopsDuration, 

SUM (
    case speedKPH 
    when 0 then 0 
    else 1 
    end) as tripDuration, 

(MAX(odometerKM) - MIN(odometerKM))/Device.fuelEconomy as fuelConsumption 

FROM EventData 
Join Device ON Device.deviceID = EventData.deviceID 

WHERE deviceID = ? AND timestamp >= ? AND timestamp <= ? 

GROUP BY DeviceID 
0

我摆脱了列子查询。你可以计算stopsDurationtripDuration这样的(我离开了fuelConsumption现在):

SELECT 
    MAX(timestamp) as end, MIN(timestamp) as start, 
    MAX(odometerKM) - MIN(odometerKM) as distanceTravelled, 
    COUNT(speedKPH = 0 AND timestamp >= ? AND timestamp <= ?) as stopsDuration 
    COUNT(speedKPH != 0 AND timestamp >= ? AND timestamp <= ?) as tripDuration 
FROM EventData WHERE deviceID = ? AND timestamp >= ? AND timestamp <= ? 

您可以通过交叉连接到Device表的单排适用摆脱fuelComparison子查询的

SELECT 
    (MAX(odometerKM) - MIN(odometerKM))/dv.fuelEconomy as fuelConsumption 
FROM 
    EventData, 
    (SELECT Device.fuelEconomy FROM Device WHERE DeviceId = ?) dv 
WHERE deviceID = ? AND timestamp >= ? AND timestamp <= ? 

把它放在一起,你会得到这一点,这(至少在纸)应该会更快:

SELECT 
    MAX(timestamp) as end, MIN(timestamp) as start, 
    MAX(odometerKM) - MIN(odometerKM) as distanceTravelled, 
    COUNT(speedKPH = 0 AND timestamp >= ? AND timestamp <= ?) as stopsDuration 
    COUNT(speedKPH != 0 AND timestamp >= ? AND timestamp <= ?) as tripDuration, 
    (MAX(odometerKM) - MIN(odometerKM))/dv.fuelEconomy as fuelConsumption 
FROM 
    EventData, 
    (SELECT Device.fuelEconomy FROM Device WHERE DeviceId = ?) dv 
WHERE deviceID = ? AND timestamp >= ? AND timestamp <= ? 
+0

为了减少它,不是最好创造另一个子查询表与WHERE条件和消除所有的地方? – Shubham

+0

我想过,但我不确定它是否会打破'start'和/或'end'和/或'distanceTravelled'值。我从来没有打算测试这个,所以我在做了100%确定的事情之后就停止了。如果你可以减少这一点,你绝对应该把它作为答案。随意使用我的查询作为起点 - 我根本没有问题:) –

相关问题