Frage

Vorausgesetzt, ich habe eine Tabelle mit folgendem, sehr einfachem Inhalt:

# select * from messages;
  id | verbosity 
 ----+-----------
   1 |        20
   2 |        20
   3 |        20
   4 |        30
   5 |       100
 (5 rows)

Ich möchte N Nachrichten auswählen, deren Ausführlichkeitssumme niedriger als Y ist (zu Testzwecken sagen wir, es sollte 70 sein, dann sind korrekte Ergebnisse Nachrichten mit der ID 1,2,3).Es ist mir wirklich wichtig, dass die Lösung datenbankunabhängig ist (sie sollte zumindest auf Postgres und SQLite funktionieren).

Ich habe es mit so etwas versucht:

SELECT * FROM messages GROUP BY id HAVING SUM(verbosity) < 70;

Es scheint jedoch nicht wie erwartet zu funktionieren, da nicht alle Werte aus der Ausführlichkeitsspalte summiert werden.

Für Hinweise / Hilfe wäre ich sehr dankbar.

War es hilfreich?

Lösung

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;

Dies setzt eine eindeutige, aufsteigende id so wie du es in deinem Beispiel getan hast.


In modernen Postgres - oder generell mit modernes Standard-SQL (aber nicht in SQLite):

Einfacher WAK

WITH cte AS (
   SELECT *, sum(verbosity) OVER (ORDER BY id) AS total
   FROM   messages
   )
SELECT *
FROM   cte
WHERE  total <= 70
ORDER  BY id;

Rekursiver WAK

Sollte für große Tische schneller sein, an denen Sie nur einen kleinen Satz abrufen.

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 Standardfunktionen, außer LIMIT.

Streng genommen gibt es so etwas wie "datenbankunabhängig" nicht.Es gibt verschiedene SQL-Standards, aber kein RDBMS entspricht vollständig. LIMIT funktioniert für PostgreSQL und SQLite (und einige andere).Verwenden TOP 1 für SQL Server, rownum für Oracle.Hier ist ein umfassende Liste auf Wikipedia.

Der SQL: Standard 2008 wäre:

...
FETCH  FIRST 1 ROWS ONLY

...welches PostgreSQL unterstützt - aber kaum ein anderes RDBMS.

Die reine Alternative, die mit mehr Systemen funktioniert, wäre, sie in eine Unterabfrage einzuschließen und

SELECT max(total) FROM <subquery>

Aber das ist langsam und unhandlich.

SQL-Geige.

Andere Tipps

Das wird funktionieren ...

generasacodicetagpre.

Sie sollten jedoch verstehen, dass SQL als festgelegte Set-basierte Sprache, anstatt ein iterativer, so konzipiert ist, so dass es so ausgelegt ist, dass Daten als Set als Set, nicht auf einer Reihe von Zeilenbasis, behandelt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top