2012-05-14 80 views
0

在我的一個應用程序中,我需要計算考慮到完全加油和部分加油的燃油消耗量。我的Android應用程序基於SQLite的語法和功能。加油計算(全部和部分)

我嘗試在SQL中解決這個難題,並且不希望遍歷所有行以編程方式執行此操作。

FULL ='N'的行應該排除在結果列表中,但它們的值應該添加到下一個FULL ='Y'行。至少這是我的想法。

這是DML(僅顯示所需的列):

CREATE TABLE FUELINGS (
ID INTEGER PRIMARY KEY, 
MILEAGE INTEGER, 
VOLUME DECIMAL(8, 2), 
FULL CHAR(1)); 

下面是一些輸入到這個表:

INSERT INTO FUELINGS VALUES(1,22995,29.48,'Y'); 
INSERT INTO FUELINGS VALUES(2,23385,31.27,'Y'); 
INSERT INTO FUELINGS VALUES(3,23869,16.71,'N'); 
INSERT INTO FUELINGS VALUES(4,24065,33.18,'Y'); 
INSERT INTO FUELINGS VALUES(5,24485,30.59,'Y'); 
INSERT INTO FUELINGS VALUES(6,24956,33.78,'Y'); 

好了,來這裏的問題。這是我使用的查詢:

SELECT T2.MILEAGE, 
     T2.VOLUME, 
     T2.FULL, 
     T2.PREVMILEAGE, 
     T2.PREVVOLUME, 
     T2.PREVFULL, 
     100 * T2.VOLUME/(T2.MILEAGE - T2.PREVMILEAGE) 
FROM (SELECT T.MILEAGE, 
       T.VOLUME, 
       T.FULL, 
       T.PREVMILEAGE, 
       (SELECT VOLUME 
       FROM FUELINGS 
       WHERE MILEAGE = T.PREVMILEAGE 
         AND MILEAGE IS NOT NULL 
         AND MILEAGE > 0 
         AND VOLUME IS NOT NULL 
         AND VOLUME > 0) AS PREVVOLUME, 
       (SELECT FULL 
       FROM FUELINGS 
       WHERE MILEAGE = T.PREVMILEAGE 
         AND MILEAGE IS NOT NULL 
         AND MILEAGE > 0 
         AND VOLUME IS NOT NULL 
         AND VOLUME > 0) AS PREVFULL 
     FROM (SELECT F.MILEAGE, 
         F.VOLUME, 
         F.FULL, 
         (SELECT Max(MILEAGE) 
         FROM FUELINGS PREV 
         WHERE PREV.MILEAGE < F.MILEAGE 
           AND MILEAGE IS NOT NULL 
           AND MILEAGE > 0 
           AND VOLUME IS NOT NULL 
           AND VOLUME > 0) AS PREVMILEAGE 
       FROM FUELINGS F 
       WHERE MILEAGE IS NOT NULL 
         AND MILEAGE > 0 
         AND VOLUME IS NOT NULL 
         AND VOLUME > 0) AS T 
     WHERE PREVMILEAGE IS NOT NULL) AS T2 
ORDER BY T2.MILEAGE; 

這是結果:

T2.MILEAGE T2.VOLUME T2.FULL T2.PREVMILEAGE T2.PREVVOLUME T2.PREVFULL 100 * T2.VOLUME/(T2.MILEAGE - T2.PREVMILEAGE) 
23385 31.27 Y 22995 29.48 Y 8.017948717948718 
23869 16.71 N 23385 31.27 Y 3.4524793388429753 
24065 33.18 Y 23869 16.71 N 16.928571428571427 
24485 30.59 Y 24065 33.18 Y 7.283333333333333 
24956 33.78 Y 24485 30.59 Y 7.171974522292993 

16.92是錯誤的,因爲在這之前加油是部分加油。我需要總結和計算兩行。我知道可能有超過1個部分加油。但我不知道如何構建FULL ='N'值的範圍,總結它們並將它們添加到以下FULL ='Y'值。

可以請有人把我放在正確的方向。我怎樣才能做到這一點?

許多在此先感謝。

編輯/解決方案:如果你有一個名爲FuelingsFull表,只包含約滿fuelings完整信息

SELECT T.MILEAGE, 
     T.PREVMILEAGE, 
     SUM(VOLUME), 
     100 * SUM(VOLUME)/(T.MILEAGE - T.PREVMILEAGE) 
FROM (SELECT F1.MILEAGE  AS MILEAGE, 
       MAX(F2.MILEAGE) AS PREVMILEAGE 
     FROM FUELINGS F1 
       LEFT OUTER JOIN FUELINGS F2 
       ON F1.MILEAGE > F2.MILEAGE 
        AND F2.FULL = 'Y' 
        AND F2.MILEAGE IS NOT NULL 
        AND F2.MILEAGE > 0 
        AND F2.VOLUME IS NOT NULL 
        AND F2.VOLUME > 0.0 
     WHERE F1.FULL = 'Y' 
       AND F1.MILEAGE IS NOT NULL 
       AND F1.MILEAGE > 0 
       AND F1.VOLUME IS NOT NULL 
       AND F1.VOLUME > 0.0 
     GROUP BY F1.MILEAGE) AS T, 
     (SELECT VOLUME 
     FROM FUELINGS F3 
     WHERE F3.MILEAGE > T.PREVMILEAGE 
       AND F3.MILEAGE <= T.MILEAGE) 
GROUP BY T.MILEAGE 

回答

0

原始查詢會工作。這可以從燃油中總結出來。這個過程對於窗口函數來說會更簡單,但在SQLite中沒有。

所以,這裏是一個關於如何做到這一點的想法。首先,得到了一次完整ID:

select f1.id, max(f2.full) as prevFullId 
from fuelings f1 left outer join 
    fuelings f2 
    on f1.id > f2.id and 
     f2.full = 0 
group by f1.id 

現在,你有一組fuelings的所有屬於彼此。下一個查詢將它加入到加油中,然後將這些加在一起。

select fills.id, max(mileage) as mileage, sum(volume) as volume, count(*) as numFills 
from fuelings f join 
    (select f1.id, max(f2.full) as prevFullId 
     from fuelings f1 left outer join 
      fuelings f2 
      on f1.id > f2.id and 
       f2.full = 1 
     group by f1.id 
    ) fills 
    on f.id > fills.prevFullId and f.id <= fills.id 
    group by fills.id 

以此爲您FuelingFull,你原來的查詢應該工作。

+0

我沒有立即理解你的想法,第一次測試沒有按預期工作,但這個想法非常好。我會根據你的答案來解決我的問題。非常感謝。 –