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

Aperta Adatta ai principianti
#2,365 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
76/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
databases

Direzione di ricerca

Inizia in packages/db/src/query/compiler/group-by.ts, dove l’issue indica che valueExtractor e minMaxInput convertono null in 0. Segui il percorso di questi valori fino ai reducer di aggregazione, poi controlla i test di aggregazione esistenti. Il lavoro è completo quando null viene escluso da avg, min, max e sum e i gruppi contenenti solo null restituiscono null, come descritto; verifica l’esempio di query raggruppata segnalato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

  • 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/

Lingua principale
TypeScript
Stelle
4k
Fork
280
Merge medio
1g 10h
PR unite (30g)
132

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di TanStack/db

Tutte le issue di TanStack/db

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.