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

Ouverte Adaptée aux débutants
#2,365 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
76/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
typescript
Domaine
databases

Piste de recherche

Commence dans packages/db/src/query/compiler/group-by.ts, où l’issue indique que valueExtractor et minMaxInput convertissent null en 0. Suis le cheminement de ces valeurs jusqu’aux réducteurs d’agrégation, puis vérifie les tests d’agrégation existants. Le travail est terminé lorsque null est exclu de avg, min, max et sum, et que les groupes contenant uniquement null renvoient null, comme indiqué ; vérifie l’exemple de requête groupée fourni.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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

Langage dominant
TypeScript
Étoiles
4k
Forks
280
Merge moyen
1 j 10 h
PR mergées (30 j)
132

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de TanStack/db

Toutes les issues de TanStack/db

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.