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

Aberta Para iniciantes
#2,365 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
76/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
typescript
Domínio
databases

Direção de pesquisa

Comece em packages/db/src/query/compiler/group-by.ts, onde o issue identifica valueExtractor e minMaxInput como responsáveis por converter null em 0. Acompanhe como esses valores chegam aos reducers de agregação e, em seguida, confira os testes de agregação existentes. O trabalho estará concluído quando null for excluído de avg, min, max e sum, e grupos contendo apenas null retornarem null, conforme descrito; verifique o exemplo de consulta agrupada relatado.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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

Linguagem predominante
TypeScript
Estrelas
4k
Forks
280
Merge médio
1d 10h
PRs com merge (30d)
132

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de TanStack/db

Todas as issues de TanStack/db

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.