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;
Dit veronderstelt een unieke, oplopende id
zoals je in je voorbeeld hebt.
In het moderne Postgres - of in het algemeen met moderne standaard SQL (maar niet in SQLite):
Eenvoudige CTE
WITH cte AS (
SELECT *, sum(verbosity) OVER (ORDER BY id) AS total
FROM messages
)
SELECT *
FROM cte
WHERE total <= 70
ORDER BY id;
Recursieve CTE
Zou sneller moeten zijn voor grote tafels waar je maar een kleine set ophaalt.
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;
Alle standaardfuncties, behalve LIMIT
.
Strikt genomen bestaat er niet zoiets als "database-onafhankelijk". Er zijn verschillende SQL-standaarden, maar geen enkele RDBMS voldoet volledig. LIMIT
werkt voor PostgreSQL en SQLite (en enkele anderen). Gebruik TOP 1
voor SQL Server, rownum
voor Orakel. Hier is een uitgebreide lijst op Wikipedia.
De SQL:2008-standaard zou zijn:
...
FETCH FIRST 1 ROWS ONLY
... die PostgreSQL ondersteunt - maar nauwelijks andere RDBMS.
Het pure alternatief dat met meer systemen werkt, zou zijn om het in een subquery te verpakken en
SELECT max(total) FROM <subquery>
Maar dat is traag en onpraktisch.
SQL Fiddle.