sql >> Databasteknik >  >> RDS >> PostgreSQL

SQL välj element där summan av fältet är mindre än N

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.



  1. Är det bättre att skapa ett index innan du fyller en tabell med data, eller efter att data är på plats?

  2. ADDDATE() vs DATE_ADD() i MySQL:Vad är skillnaden?

  3. MySql Single Table, Välj de senaste 7 dagarna och inkludera tomma rader

  4. Hur LocalTime() fungerar i PostgreSQL