PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

SQL wybierz elementy, w których suma pola jest mniejsza niż 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;

Zakłada to unikalny, rosnąco id jak masz w swoim przykładzie.

We współczesnym Postgresie – lub ogólnie w nowoczesnym standardowym SQL (ale nie w SQLite):

Proste CTE

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

Rekursywne CTE

Powinno być szybsze w przypadku dużych stołów, gdzie pobierasz tylko mały zestaw.

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;

Wszystkie standardowe funkcje, z wyjątkiem LIMIT .

Ściśle mówiąc, nie ma czegoś takiego jak „niezależność od bazy danych”. Istnieją różne standardy SQL, ale żaden RDBMS nie jest w pełni zgodny. LIMIT działa dla PostgreSQL i SQLite (i kilku innych). Użyj TOP 1 dla SQL Server, rownum dla Oracle. Oto pełna lista w Wikipedii.

Standard SQL:2008 to:

...
FETCH  FIRST 1 ROWS ONLY

... które obsługuje PostgreSQL - ale prawie żadnych innych RDBMS.

Czystą alternatywą, która działa z większą liczbą systemów, byłoby umieszczenie go w podzapytaniu i

SELECT max(total) FROM <subquery>

Ale to jest powolne i nieporęczne.

Skrzypce SQL.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wdrażanie i skalowanie PostgreSQL v13 za pomocą ClusterControl 1.8.2

  2. Przekazywanie param do DB .execute dla listy WHERE IN... INT

  3. Wiele wywołań array_agg() w jednym zapytaniu

  4. Użytkownicy aplikacji a zabezpieczenia na poziomie wiersza

  5. Dołącz do zapytania licznika w generate_series() i pobierz wartości Null jako „0”