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. Ето изчерпателен списък в Wikipedia.
Стандартът SQL:2008 би бил:
...
FETCH FIRST 1 ROWS ONLY
... който PostgreSQL поддържа - но едва ли има друга RDBMS.
Чистата алтернатива, която работи с повече системи, би била да я обвиете в подзаявка и
SELECT max(total) FROM <subquery>
Но това е бавно и тромаво.
SQL Fiddle.