{
  "category": "Database functions",
  "display_name": "DAVERAGE",
  "entry_kind": "built_in_function",
  "eval_api": {
    "method": "POST",
    "url": "https://handbook.dnacalc.com/api/eval"
  },
  "function_id": "FUNC.DAVERAGE",
  "implementation_state": {
    "answer_bank": null,
    "detail": "Recorded: 3 workbook cells.",
    "dnacalc_commit": "9e1884369a678158dd82d3d74188daf986995e87",
    "in_catalogue": true,
    "state": "matches",
    "state_label": "Matches every recorded Excel answer",
    "summary": "Matches all 3 recorded answers",
    "workbook_corpus": {
      "cells": 3,
      "matched": 3
    }
  },
  "implementations": [
    {
      "commit": "9e1884369a678158dd82d3d74188daf986995e87",
      "flavour": "excel-compatibility-candidate",
      "language": "Rust",
      "name": "CalcFunc",
      "own_code": [
        "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/database.rs#L264-L264"
      ],
      "repository": "https://github.com/DnaCalc/DnaCalc",
      "shared_code": [
        "catalogue/aggregate::reader",
        "catalogue/aggregate::read_reference",
        "catalogue/comparison::numbers",
        "catalogue/comparison::in_band",
        "catalogue/comparison::Rounded::up",
        "catalogue/comparison::Roundings::of",
        "catalogue/comparison::Roundings::disjoint",
        "catalogue/comparison::texts",
        "catalogue/comparison/collation::compare",
        "catalogue/comparison/collation::weighed",
        "catalogue/comparison/collation::measured_iteration_extension",
        "catalogue/comparison/sort_key::table",
        "catalogue/comparison/sort_key::decode64",
        "catalogue/comparison/sort_key::Reader::byte",
        "catalogue/comparison/sort_key::Reader::varint",
        "catalogue/comparison/sort_key::Reader::done",
        "catalogue/comparison/sort_key::in_ranges",
        "catalogue/comparison/sort_key::build",
        "catalogue/comparison/sort_key::han_base",
        "catalogue/comparison/sort_key::derive",
        "catalogue/comparison/sort_key::shared_jamo_tails",
        "catalogue/comparison/sort_key::ordinary_jamo_prefix",
        "catalogue/comparison/sort_key::independent_jamo_suffix",
        "catalogue/comparison/sort_key::jamo_leading_primary",
        "catalogue/comparison/sort_key::leading_order",
        "catalogue/comparison/sort_key::Before::separate_special",
        "catalogue/comparison/sort_key::Gathered::kana",
        "catalogue/comparison/sort_key::Gathered::unit",
        "catalogue/comparison/sort_key::parts",
        "catalogue/comparison/sort_key::diacritic_order",
        "catalogue/comparison/sort_key::diacritics",
        "catalogue/conditional::range",
        "catalogue/conditional::row",
        "catalogue/conditional::offset",
        "catalogue/conditional::read_range",
        "catalogue/conditional::verdicts",
        "catalogue/conditional::used",
        "catalogue/conditional::Match::of",
        "catalogue/conditional::Match::negated",
        "catalogue/conditional::Op::holds",
        "catalogue/conditional::Op::is_equality",
        "catalogue/conditional::spells",
        "catalogue/conditional::criterion",
        "catalogue/conditional::database_criterion",
        "catalogue/conditional::rank",
        "catalogue/conditional::criterion_text",
        "catalogue/conditional::decided",
        "catalogue/conditional::Criterion::verdict",
        "catalogue/conditional::equality",
        "catalogue/conditional::is_surrogate",
        "catalogue/conditional::wildcard",
        "catalogue/database::label",
        "catalogue/database::same_label",
        "catalogue/database::field",
        "catalogue/database::matching",
        "catalogue/database::criterion_verdict",
        "catalogue/database::database",
        "catalogue/database::published",
        "decimal::low32",
        "decimal::Natural::from_u64",
        "decimal::Natural::pow10",
        "decimal::Natural::normalize",
        "decimal::Natural::is_zero",
        "decimal::Natural::mul_add_small",
        "decimal::Natural::times_pow10",
        "decimal::Natural::times_pow5",
        "decimal::Natural::times_pow2",
        "decimal::ExactDecimal::binary",
        "ported/excel_numeric::excel_sqrt_staged",
        "ported/text_kernels::text",
        "ported/text_kernels::text_from_str",
        "ported/text_kernels::fold_unit",
        "ported/text_kernels::push_singleton_or_original",
        "ported/text_kernels::push_lower",
        "ported/text_kernels::lower",
        "ported/variance_common::variance_from_values",
        "ported/variance_common::stdev_from_values"
      ],
      "source": "https://github.com/DnaCalc/DnaCalc/blob/9e1884369a678158dd82d3d74188daf986995e87/crates/calc-func/src/catalogue/database.rs#L264-L264",
      "state": "matches",
      "suite": null,
      "summary": "Matches all 3 recorded answers"
    }
  ],
  "json_url": "https://handbook.dnacalc.com/api/functions/FUNC.DAVERAGE.json",
  "name": "DAVERAGE",
  "notes": [],
  "schema": "efh.function-reference/v1",
  "section_order": [
    "what-it-does",
    "try-it",
    "quirks",
    "how-to-implement",
    "version-differences",
    "alternatives"
  ],
  "sections": {
    "alternatives": "\n### Relationships\n\n- **Siblings**: the twelve-member database family, all sharing the mechanism above and differing\n  only in the aggregate. See the family list at the head of that section.\n- **Nearest modern equivalent**: `AVERAGEIFS`, which expresses the same filtered-average idea\n  with inline condition arguments instead of a criteria grid. It is not a replacement — Excel\n  supports both, and the D-functions remain the only members of this group that take criteria as\n  a *worksheet-resident table*, which is what makes them useful when the conditions are meant to\n  be edited by the user rather than by the formula author.\n- **Confused with**: `AVERAGE` (no selection stage), `AVERAGEA` (counts text and logicals),\n  and `SUBTOTAL`/`AGGREGATE` (filter-aware, but by hidden rows rather than by criteria).\n\n\n",
    "how-to-implement": "\n### Notes for implementers\n\n1. **Resolve in the documented order.** Parse the database grid, then the criteria grid, then\n   the field index, then match. The field index must be resolved against the database headers,\n   which means a bad field argument is detectable before any row is examined — and the order\n   determines which error wins when more than one argument is wrong.\n2. **Do not use `==` on doubles for numeric criteria.** See the comparison note above.\n3. **Reduction order is observable.** The family declares a sequential left fold; summing the\n   matched values in record order and dividing at the end is not the same in the last bits as\n   any reassociated or pairwise sum. Two implementations that disagree only in summation order\n   will disagree on long, badly-scaled columns.\n5. **The empty criteria grid is a real input.** A criteria range with only a header row selects\n   every record. So does a criteria row whose cells are all blank. Both are easy to get wrong by\n   treating \"no predicates\" as \"no matches\".\n\n\n",
    "quirks": "\n### The criteria-range mechanism\n\n\n*This section is the family's shared explanation. The other eleven database functions —\n[DCOUNT](FUNC.DCOUNT.md), [DCOUNTA](FUNC.DCOUNTA.md), [DGET](FUNC.DGET.md),\n[DMAX](FUNC.DMAX.md), [DMIN](FUNC.DMIN.md), [DPRODUCT](FUNC.DPRODUCT.md),\n[DSTDEV](FUNC.DSTDEV.md), [DSTDEVP](FUNC.DSTDEVP.md), [DSUM](FUNC.DSUM.md),\n[DVAR](FUNC.DVAR.md), [DVARP](FUNC.DVARP.md) — link here instead of repeating it.*\n\n### The database grid\n\n*database* is a rectangular range or array. Its **first row is a header row**: each cell of it\nnames a field. Every row below the first is one **record**. The header row is never a record\nand never participates in matching as data — it participates only as a set of column names.\n\nHeader cells are label-valued: text is used as written; a number or a logical in the header row\nis turned into its label form for matching purposes. A blank header cell leaves that column\nunnameable, and an error value anywhere in the header row is a hard failure rather than a\nskipped column.\n\n### The field argument\n\n*field* names one column of *database*, in either of two forms:\n\n- **as text** — the header label of the column, e.g. `\"Yield\"`;\n- **as a number** — the 1-based column index counting from the left edge of *database*, so `1`\n  is the leftmost column of the database range, not of the worksheet.\n\nBoth forms are documented by Microsoft. The index form is the position within the given range,\nwhich is the argument position most often misread when the database range does not start at\ncolumn A.\n\n### The criteria grid\n\n*criteria* is a rectangular range or array with **its own header row** and one or more rows of\nconditions beneath it. It is a small second table whose column headers say which database field\neach condition applies to. Its shape is independent of the database's: it may name a subset of\nthe fields, in any order, and may name the same field more than once.\n\nThe matching rule has four parts, and they compose in exactly this order:\n\n1. **Header matching.** For each column of the criteria grid that holds a condition, the\n   criteria header is matched against the database's header labels to find the target column.\n   The criteria header is what binds a condition to a field — position is irrelevant.\n2. **AND across a row.** Within one criteria row, every populated condition cell must hold. A\n   record matches that row only if it satisfies all of them.\n3. **OR down the rows.** A record is selected if it satisfies *any* criteria row. Multiple rows\n   are alternatives.\n4. **Blank means no condition.** An empty criteria cell contributes no predicate. This has a\n   consequence readers hit in practice: a criteria row that is entirely blank imposes nothing at\n   all, so it matches every record and, by rule 3, makes the whole criteria range vacuous. An\n   accidental blank row inside the criteria range silently turns a filtered aggregate into an\n   unfiltered one. Likewise, a criteria range consisting of a header row with no condition rows\n   beneath it selects every record.\n\n### How a criteria cell is parsed\n\nA populated criteria cell is compiled into a comparison operator plus an operand:\n\n| Cell content | Operator | Operand |\n|---|---|---|\n| A number | `=` | that number |\n| A logical | `=` | that logical |\n| Text starting with `<=`, `>=`, `<>`, `<`, `>` or `=` | that operator | the remainder of the text, re-parsed |\n| Any other text | `=` with **prefix** semantics | the text |\n| Text that is empty, or an operator with nothing after it | the operator | the *blank* operand |\n\nThe re-parse of the remainder is ordered: it is tried as a number first, then as the logical\nwords `TRUE`/`FALSE`, and only then kept as text. So `\">=100\"` is a numeric comparison and\n`\">=abc\"` is a text comparison, decided by what the right-hand side looks like, not by the\ncolumn's contents.\n\nThree consequences worth stating separately:\n\n- **Bare text is a prefix match, not an equality match.** A criteria cell containing `Nor`\n  selects `Norway` and `Northwind`. Writing `=\"Nor\"` — an explicit `=` operator — asks for\n  whole-value equality instead. This is the single most common surprise in the family, and it is\n  documented behaviour on Microsoft's side.\n- **`*` and `?` are wildcards** in equality and inequality comparisons on text, with `~` as the\n  escape prefix for a literal `*` or `?`.\n- **The blank operand is how you test emptiness.** A cell containing just `=` selects records\n  whose field cell is blank; a cell containing just `<>` selects records whose field cell is not\n  blank.\n\n### Numeric comparison is not exact double comparison\n\n### What is outside the described mechanism\n\n\n### Result and edge cases\n\n\nReturns a Number.\n\n- **Text that looks numeric in the field column** is not averaged. The field-column scan admits\n  only cells whose value kind is Number; a cell holding the text `\"3\"` is skipped. This follows\n  the range-scan side of the direct-versus-scan asymmetry described in\n  [coercion and lifting](../model/02-coercion-and-lifting.md#direct-arguments-versus-range-scans),\n  and the family is registered there as carrying its own policy row.\n- **Logicals in the field column** are skipped for the same reason.\n- **Blank cells in the field column** are skipped — they do not pull the mean toward zero.\n- **Arrays**: an inline array literal is accepted wherever a range is, because both resolve to a\n  grid. `DAVERAGE` is not a lift kernel — an array argument is consumed whole, never mapped\n  elementwise.\n\n\n\n### Errors\n\n| Error | Condition |\n|---|---|\n| `#VALUE!` | *database* or *criteria* is not a grid, or is empty; a header cell in *database* is blank; a criteria header names no database field; *field* is text that matches no header, a non-integer or out-of-range column index, or a value of an unusable kind |\n| `#DIV/0!` | No numeric value was collected from the field column of the matching records |\n| propagated | An error value in a header cell, a criteria cell, or a scanned field cell surfaces as that error |\n\n",
    "sources": "- Microsoft, \"DAVERAGE function\" —\n  <https://support.microsoft.com/en-us/office/daverage-function-a6a2d5ac-4b4b-48cd-a1d8-7b37834e5aee>\n  (argument roles, the criteria-range convention, prefix and wildcard matching).\n- Handbook `CHARTER.md` sections 1, 3 and 7; `content/model/06-claim-language.md` (claim\n  language and the scoping rules this page is written under).\n- Handbook call-model chapters 01, 02 and 03 (value kinds, Missing versus Empty, the\n  direct-argument versus range-scan asymmetry, argument preparation and error folding).\n- `data/functions/FUNC.DAVERAGE.json`, `data/presence/FUNC.DAVERAGE.json` (arity, classification\n  axes, implementing module).\n\n",
    "version-differences": "No comparison between specific Excel builds is recorded here yet. This does not establish that all builds behave alike.",
    "what-it-does": "\n`DAVERAGE(database, field, criteria)` selects the records of *database* that satisfy\n*criteria*, reads one column of those records — the column named by *field* — and returns the\narithmetic mean of the numeric values it finds there.\n\nWritten out: let R be the set of record rows selected by the criteria mechanism below, let c be\nthe resolved field column, and let\n\n    V = [ v : v = value of cell (r, c) for r in R, in record order, where v is a Number ]\n\nThen the result is (Σ V) / |V|. Non-numeric cells in the field column — text, logicals, blanks —\nare not in V at all: they are neither counted in the denominator nor treated as zero. If V is\nempty the quotient is undefined and the function is in error territory (see *Result and edge\ncases*).\n\nTwo things this definition deliberately makes explicit, because Microsoft's one-line\ndescription (\"Returns the average of selected database entries\") does not:\n\n*The quoted one-line description is Microsoft's text, from its support article <https://support.microsoft.com/en-us/office/daverage-function-a6a2d5ac-4b4b-48cd-a1d8-7b37834e5aee>.*\n\n1. **Selection and aggregation are separate stages.** The criteria mechanism picks *rows*; the\n   field argument picks a *column*; the aggregate runs over the intersection. Every one of the\n   twelve D-functions shares the first two stages exactly and differs only in the third.\n2. **The denominator is a count of numbers, not of records.** A record can match the criteria\n   and still contribute nothing, if its cell in the field column is blank or non-numeric.\n\n\n\n### Arguments\n\n\nThree arguments, all required at the call site; the reference implementation declares an arity\nof exactly 3.\n\n- **`database`** — the header-plus-records range or array. A scalar is not a table and fails.\n- **`field`** — the column selector: header text or 1-based column index within *database*. For\n  `DAVERAGE` the field is genuinely required; the omitted-field convenience exists only for\n  [DCOUNT](FUNC.DCOUNT.md) and [DCOUNTA](FUNC.DCOUNTA.md).\n- **`criteria`** — the header-plus-conditions range or array described above.\n\nNote the interaction with the call model: leaving the middle slot empty, as in\n`DAVERAGE(A1:C9,,E1:F2)`, still passes three arguments. The empty slot delivers the `Missing`\nmarker described in [the value universe](../model/01-value-universe.md#missing-versus-empty),\nnot a shorter call, which is why an arity of exactly 3 and an \"omitted field\" behaviour are not\nin conflict.\n\n"
  },
  "signature": {
    "display": "DAVERAGE(database, field, criteria)",
    "parameters": [
      {
        "description": null,
        "name": "database",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "field",
        "optional": false,
        "repeats": false
      },
      {
        "description": null,
        "name": "criteria",
        "optional": false,
        "repeats": false
      }
    ],
    "trailing_repeats": false
  },
  "sources": {
    "metadata": {
      "admission": {
        "label": "implemented",
        "reason": null
      },
      "arity": {
        "max": 3,
        "min": 3
      },
      "category": "Database functions",
      "classification": {
        "arg_preparation_profile": "RefsVisibleInAdapter",
        "coercion_lift_profile": "Custom",
        "determinism_class": "Deterministic",
        "error_collapse_profile": "ReductionFold",
        "fec_dependency_profile": "RefOnly",
        "host_interaction_class": "None",
        "kernel_signature_class": "Custom",
        "rich_value_usage": "RichBlind",
        "surface_fec_dependency_profile": "RefOnly",
        "thread_safety_class": "SafePure",
        "volatility_class": "NonVolatile"
      },
      "descriptions": {
        "long": null,
        "short": "Mean of a database column over the records that match the criteria",
        "short_source": "dna-calc-own"
      },
      "docs": {
        "english_description": "Returns the average of selected database entries",
        "microsoft_url": "https://support.microsoft.com/en-us/office/daverage-function-a6a2d5ac-4b4b-48cd-a1d8-7b37834e5aee"
      },
      "entry_kind": "built_in_function",
      "localized_family_names": null,
      "localized_names": [
        {
          "locale": "ar-SA",
          "name": "DAVERAGE"
        },
        {
          "locale": "bg-BG",
          "name": "DAVERAGE"
        },
        {
          "locale": "cs-CZ",
          "name": "DPRŮMĚR"
        },
        {
          "locale": "da-DK",
          "name": "DMIDDEL"
        },
        {
          "locale": "de-DE",
          "name": "DAVERAGE"
        },
        {
          "locale": "el-GR",
          "name": "DAVERAGE"
        },
        {
          "locale": "en-AU",
          "name": "DAVERAGE"
        },
        {
          "locale": "en-GB",
          "name": "DAVERAGE"
        },
        {
          "locale": "en-US",
          "name": "DAVERAGE"
        },
        {
          "locale": "es-ES",
          "name": "BDPROMEDIO"
        },
        {
          "locale": "et-EE",
          "name": "DAVERAGE"
        },
        {
          "locale": "fi-FI",
          "name": "TKESKIARVO"
        },
        {
          "locale": "fr-FR",
          "name": "BDMOYENNE*"
        },
        {
          "locale": "he-IL",
          "name": "DAVERAGE"
        },
        {
          "locale": "hr-HR",
          "name": "DAVERAGE"
        },
        {
          "locale": "hu-HU",
          "name": "AB.ÁTLAG"
        },
        {
          "locale": "id-ID",
          "name": "DAVERAGE"
        },
        {
          "locale": "it-IT",
          "name": "DAVERAGE"
        },
        {
          "locale": "ja-JP",
          "name": "DAVERAGE"
        },
        {
          "locale": "ko-KR",
          "name": "DAVERAGE"
        },
        {
          "locale": "lt-LT",
          "name": "DAVERAGE"
        },
        {
          "locale": "lv-LV",
          "name": "DAVERAGE"
        },
        {
          "locale": "nb-NO",
          "name": "DGJENNOMSNITT"
        },
        {
          "locale": "nl-NL",
          "name": "DBGEMIDDELDE"
        },
        {
          "locale": "pl-PL",
          "name": "BD.ŚREDNIA"
        },
        {
          "locale": "pt-BR",
          "name": "DAVERAGE"
        },
        {
          "locale": "pt-PT",
          "name": "BDMÉDIA"
        },
        {
          "locale": "ro-RO",
          "name": "DAVERAGE"
        },
        {
          "locale": "ru-RU",
          "name": "ДСРЗНАЧ"
        },
        {
          "locale": "sk-SK",
          "name": "DAVERAGE"
        },
        {
          "locale": "sl-SI",
          "name": "DAVERAGE"
        },
        {
          "locale": "sr-Latn-RS",
          "name": "DAVERAGE"
        },
        {
          "locale": "sv-SE",
          "name": "DMEDEL"
        },
        {
          "locale": "th-TH",
          "name": "DAVERAGE"
        },
        {
          "locale": "tr-TR",
          "name": "VSEÇORT işlevi"
        },
        {
          "locale": "uk-UA",
          "name": "DAVERAGE"
        },
        {
          "locale": "vi-VN",
          "name": "DAVERAGE"
        },
        {
          "locale": "zh-CN",
          "name": "DAVERAGE"
        },
        {
          "locale": "zh-HK",
          "name": "DAVERAGE"
        },
        {
          "locale": "zh-TW",
          "name": "DAVERAGE"
        }
      ],
      "signature": {
        "display": "DAVERAGE(database, field, criteria)",
        "parameters": [
          {
            "description": null,
            "name": "database",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "field",
            "optional": false,
            "repeats": false
          },
          {
            "description": null,
            "name": "criteria",
            "optional": false,
            "repeats": false
          }
        ],
        "trailing_repeats": false
      },
      "surface_name": "DAVERAGE",
      "version_marker": null,
      "xlcall": {
        "code": "42",
        "symbol": "xlfDaverage"
      }
    },
    "microsoft": "https://support.microsoft.com/en-us/office/daverage-function-a6a2d5ac-4b4b-48cd-a1d8-7b37834e5aee"
  },
  "try_it": {
    "formula": "=DAVERAGE(B2:D6,\"Amount\",F2:F3)",
    "inputs": {
      "B2": "Name",
      "B3": "A",
      "B4": "B",
      "B5": "C",
      "B6": "D",
      "C2": "Group",
      "C3": "East",
      "C4": "East",
      "C5": "West",
      "C6": "East",
      "D2": "Amount",
      "D3": 10,
      "D4": 20,
      "D5": 30,
      "D6": 40,
      "F2": "Group",
      "F3": "East"
    }
  },
  "url": "https://handbook.dnacalc.com/functions/DAVERAGE.html",
  "variants": [],
  "versions": []
}