Search code examples
sqlsqlitecorrelated-subquery

No Such Column in Correlated Subquery


So I wrote a query pretty much the same as the one described in this answer. However I'm getting an error stating that: No such column b.when.

My select statement:

SELECT
    mileage,
    (SELECT b.mileage FROM MileageEvents as b WHERE `b.when` < `a.when` ORDER BY `b.when` DESC LIMIT 1) as last_mileage,
    gallons,
    cost_per_gallon,
    `when`
FROM MileageEvents as a

I know I've written such queries previously, but I can't seem to figure out what is going on with this query. What am I doing wrong?

A dump of my database:

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "MileageEvents" (
    "mileage"   INTEGER,
    "when"  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    "cost_per_gallon"   INTEGER,
    "gallons"   INTEGER,
    "id"    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "car_id"    INTEGER NOT NULL
);
INSERT INTO MileageEvents VALUES(150000,'2019-03-12',3.3500000000000000888,12,1,1);
INSERT INTO MileageEvents VALUES(150300,'2019-03-19',3.25,12,2,1);
INSERT INTO MileageEvents VALUES(150693,'2019-03-22',3.4500000000000001776,12,3,1);
INSERT INTO MileageEvents VALUES(151000,'2019-03-25',3.3900000000000001243,12,4,1);
INSERT INTO MileageEvents VALUES(151600,'2019-04-01',2.25,12,5,1);
INSERT INTO MileageEvents VALUES(151883,'2019-06-10 23:01:43',2.4500000000000001776,11.695999999999999729,6,1);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('MileageEvents',6);
COMMIT;

Solution

  • (First, I'd use normal double quote escaping instead of MySQL style backticks, or better yet, an identifier that's not a reserved keyword)

    You need to use b."when". What you're doing treats the entire string b.when as an identifier, with no split between table name and column name.

    Rewritten:

    SELECT
        mileage,
        (SELECT b.mileage FROM MileageEvents as b WHERE b."when" < a."when" ORDER BY b."when" DESC LIMIT 1) as last_mileage,
        gallons,
        cost_per_gallon,
        "when"
    FROM MileageEvents as a;
    

    Note: if using sqlite 3.25 or newer, you can avoid the subquery completely:

    SELECT
        mileage,
        lag(mileage) OVER (ORDER BY "when") AS last_mileage,
        gallons,
        cost_per_gallon,
        "when"
    FROM MileageEvents;