`avg`, `min`, `max` and `sum` treat `null` values as `0`

Offen Anfängerfreundlich
#2,365 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
76/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
typescript
Bereich
databases

Rechercherichtung

Beginne in packages/db/src/query/compiler/group-by.ts, wo der Issue valueExtractor und minMaxInput als Stellen identifiziert, an denen null in 0 umgewandelt wird. Verfolge, wie diese Werte zu den Aggregatreduzierern gelangen, und prüfe anschließend die vorhandenen Aggregattests. Fertig ist die Arbeit, wenn null bei avg, min, max und sum ausgeschlossen wird und Gruppen, die nur null enthalten, wie beschrieben null zurückgeben; überprüfe das angegebene Beispiel für gruppierte Abfragen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

  • I've validated the bug against the latest version of DB packages

Describe the bug
In a grouped query, avg, min, max and sum turn every null value into 0 before aggregating. So min can return 0 even though no row has 0, and avg divides by the number of rows instead of the number of values. count on the same field already skips nulls, which makes the result inconsistent: count 2, sum 300, avg 100.

To Reproduce

// repro.mjs, npm i @tanstack/db
import { createCollection, localOnlyCollectionOptions, queryOnce, avg, min, max, sum, count } from "@tanstack/db"

const employees = createCollection(localOnlyCollectionOptions({
  id: "employees",
  getKey: (e) => e.id,
  initialData: [
    { id: 1, dept: "eng", salary: 100 },
    { id: 2, dept: "eng", salary: 200 },
    { id: 3, dept: "eng", salary: null }, // salary not known yet
  ],
}))

const rows = await queryOnce((q) =>
  q.from({ e: employees })
    .groupBy(({ e }) => e.dept)
    .select(({ e }) => ({
      dept: e.dept,
      count: count(e.salary),
      sum: sum(e.salary),
      avg: avg(e.salary),
      min: min(e.salary),
      max: max(e.salary),
    })))
console.log(rows.map(({ dept, count, sum, avg, min, max }) => ({ dept, count, sum, avg, min, max })))

node repro.mjs prints:

[ { dept: 'eng', count: 2, sum: 300, avg: 100, min: 0, max: 200 } ]

Expected behavior
{ dept: 'eng', count: 2, sum: 300, avg: 150, min: 100, max: 200 }, as in SQL (SELECT count(salary), sum(salary), avg(salary), min(salary), max(salary) ... GROUP BY dept gives 2|300|150.0|100|200 in SQLite), and consistent with count, which the docs describe as "Count non-null values". A group whose values are all null would give null for avg, min, max (and sum in SQL) rather than 0.

Additional context
@tanstack/db 1.0.0-rc.1.4 (npm latest), node v26.13.0. Same code on main (d054a77): in packages/db/src/query/compiler/group-by.ts, valueExtractor and minMaxInput both end with return value != null ? Number(value) : 0, so the null check in the db-ivm min/max reducers never sees a missing value.

Credit: https://ucsbplse.github.io/

Vorherrschende Sprache
TypeScript
Sterne
4k
Forks
280
Ø Merge
1 T. 10 Std.
Gemergte PRs (30 T.)
132

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus TanStack/db

Alle Issues in TanStack/db

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.