0

私のアプリの 1 つで、完全な給油と部分的な給油を考慮した燃料消費量を計算する必要があります。私の 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 は、その前の給油が部分給油だったので間違っています。両方の行を合計して計算する必要があります。部分給油が複数回発生する可能性があることは承知しています。しかし、FULL='N' 値の範囲を構築し、それらを合計して、次の FULL='Y' 値に追加する方法がわかりません。

誰かが私を正しい方向に向けてください。どうすればそれを正しくすることができますか?

よろしくお願いします。

編集/解決策:

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
4

1 に答える 1

0

元のクエリは、フル給油に関する完全な情報のみを含む FuelingsFull というテーブルがあれば機能します。これは、Fueling から要約できます。ウィンドウ関数を使用するとプロセスが簡単になりますが、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

これで、すべてが一緒に属する燃料のグループができました。次のクエリは、これを燃料に結合し、これらをグループ化します。

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 として使用すると、元のクエリが機能するはずです。

于 2012-05-14T14:23:13.353 に答える