SQLite Forum

Can this simple query be optimized?
Login
See the [db-fiddle][1].

On the following table

```
CREATE TABLE foo (x INTEGER PRIMARY KEY, y INTEGER);
INSERT INTO foo VALUES (0,41), (1, 23), (2,45), (3,32), ...
```
I need the `x` and `y` which has `min(y)` over groups of 10 `x`, and the same for `max(y)`:

```
SELECT x, min(y) FROM foo GROUP BY (x/10)
UNION
SELECT x, max(y) FROM foo GROUP BY (x/10);
```

The `EXPLAIN QUERY PLAN` output shows that two scans of the table are performed
```
`--COMPOUND QUERY
   |--LEFT-MOST SUBQUERY
   |  |--SCAN TABLE foo
   |  `--USE TEMP B-TREE FOR GROUP BY
   `--UNION ALL
      |--SCAN TABLE foo
      `--USE TEMP B-TREE FOR GROUP BY
```

**Is there any way to reword the query so that only one scan is performed?**

What I've done in the mean time is to select all rows (`SELECT x, y FROM foo;`) and manually aggregate min/max as rows are returned to the host language (C++):
```
int lastGroup = 0;
while (sqlite3_step(query) == SQLITE_ROW) {
  int x = sqlite3_column_int(query, 0);
  int y = sqlite3_column_int(query, 1);
  int group = x / 10;
  if (group != lastGroup) {
    // save minX, minY, maxX, maxY in a list somewhere
    // reset minX, minY, maxX, maxY
    // ...
    lastGroup = group;
  }  
  else {
    if (y < minY) {
      minX = x;
      minY = y;
    }
    else if (y > maxY) {
      maxX = x;
      maxY = y;
    }
  }
}
```

This achieves a single scan and the whole process is more than twice as fast... but I'd rather express this logic *declaritively* in SQL if possible. I'm kind of surprised that sqlite doesn't recognize the opportunity to do this in one scan.

  [1]: https://www.db-fiddle.com/f/xjHdxku1CMHm6ZY6LmwhB1/2