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;
Detta förutsätter ett unikt, stigande id
som du har i ditt exempel.
I modern Postgres - eller generellt med modern standard SQL (men inte i SQLite):
Enkel CTE
WITH cte AS (
SELECT *, sum(verbosity) OVER (ORDER BY id) AS total
FROM messages
)
SELECT *
FROM cte
WHERE total <= 70
ORDER BY id;
Rekursiv CTE
Bör vara snabbare för stora bord där du bara hämtar ett litet set.
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;
Alla standardfunktioner, förutom LIMIT
.
Det finns strängt taget inget som heter "databasoberoende". Det finns olika SQL-standarder, men ingen RDBMS uppfyller helt. LIMIT
fungerar för PostgreSQL och SQLite (och några andra). Använd TOP 1
för SQL Server, rownum
för Oracle. Här är en omfattande lista på Wikipedia.
SQL:2008-standarden skulle vara:
...
FETCH FIRST 1 ROWS ONLY
... som PostgreSQL stöder - men knappast något annat RDBMS.
Det rena alternativet som fungerar med fler system skulle vara att linda in det i en underfråga och
SELECT max(total) FROM <subquery>
Men det är långsamt och otympligt.
SQL-fiol.