SELECT m.id, sum(m1.verbosity) AS total
FROM messages m
JOIN messages m1 ON m1.id <= m.id
WHERE m.verbosity < 70 -- optional, to avoid pointless evaluation
GROUP BY m.id
HAVING SUM(m1.verbosity) < 70
ORDER BY total DESC
LIMIT 1;
これは、一意の昇順のid
を想定しています。 あなたの例のように。
最新のPostgresの場合-または一般的に最新の標準SQL (ただし、ではありません SQLiteで):
単純なCTE
WITH cte AS (
SELECT *, sum(verbosity) OVER (ORDER BY id) AS total
FROM messages
)
SELECT *
FROM cte
WHERE total <= 70
ORDER BY id;
再帰CTE
小さなセットのみを取得する大きなテーブルの場合は、より高速になるはずです。
WITH RECURSIVE cte AS (
( -- parentheses required
SELECT id, verbosity, verbosity AS total
FROM messages
ORDER BY id
LIMIT 1
)
UNION ALL
SELECT c1.id, c1.verbosity, c.total + c1.verbosity
FROM cte c
JOIN LATERAL (
SELECT *
FROM messages
WHERE id > c.id
ORDER BY id
LIMIT 1
) c1 ON c1.verbosity <= 70 - c.total
WHERE c.total <= 70
)
SELECT *
FROM cte
ORDER BY id;
LIMIT
を除くすべての標準機能 。
厳密に言えば、「データベースに依存しない」というものはありません。さまざまなSQL標準がありますが、RDBMSが完全に準拠しているわけではありません。 LIMIT
PostgreSQLとSQLite(およびその他のいくつか)で動作します。 TOP 1
を使用する SQL Serverの場合、rownum
Oracleの場合。これがウィキペディアの包括的なリストです。
SQL:2008標準は次のようになります:
...
FETCH FIRST 1 ROWS ONLY
...PostgreSQLがサポートしているものですが他のRDBMSはほとんどありません。
より多くのシステムで機能する純粋な代替手段は、サブクエリでラップして
することです。SELECT max(total) FROM <subquery>
しかし、それは遅くて扱いにくいです。
SQLフィドル。