ExportXMLWordPrintableJSON

    • Type: New Feature
    • Resolution: Fixed
    • Priority: Major - P3
    • 1.0.0
    • Affects Version/s: None
    • Component/s: Query
    • None
    • 5
    • None
    • Needed
    • Hide

      Add a code examples of HQL that has aggregate functions in select and/or having

      SELECT p.customer, count(*) FROM Purchase p GROUP BY p.customer HAVING count(*) > 1

      The aggregate functions without group by are not supported and are tracked here 

      https://jira.mongodb.org/browse/HIBERNATE-262 

      Show
      Add a code examples of HQL that has aggregate functions in select and/or having SELECT p.customer, count(*) FROM Purchase p GROUP BY p.customer HAVING count(*) > 1 The aggregate functions without group by are not supported and are tracked here  https://jira.mongodb.org/browse/HIBERNATE-262  
    • None
    • None
    • None
    • None
    • None
    • None

      This ticket adds accumulator support so that aggregate functions can be used in the SELECT list and in the HAVING clause of a grouped query.

      SELECT p.country, COUNT(*), SUM(p.amount)
      FROM Payment p
      GROUP BY p.country
      HAVING COUNT(*) > 1
      

      MongoDB mapping

      Each aggregate function becomes an accumulator field in the $group stage.

      An aggregate in SELECT is projected normally:

      [
        {"$group": {"_id": {"country": "$country"}, "#count_0": {"$sum": 1}, "#sum_0": {"$sum": "$amount"}}},
        {"$project": {"_id#country": "$_id.country", "#count_0": "$#count_0", "#sum_0": "$#sum_0"}}
      ]
      

      An aggregate that appears only in HAVING is computed per group for filtering and must not appear in the result, so it is added as a hidden accumulator and excluded from $project:

      [
        {"$group": {"_id": {"country": "$country"}, "_having_0": {"$sum": 1}}},
        {"$match": {"_having_0": {"$gt": 1}}},
        {"$project": {"_id#country": "$_id.country", "_having_0": 0}}
      ]
      

      Aggregate functions in ORDER BY resolve to their accumulator field already registered in $group.

      Implementation approach

      • Each aggregate function encountered registers a named accumulator (for example #count_0) in GroupByContext and yields a field reference to it.
      • The $group stage emits both group keys and registered accumulators.
      • $sort and $project reference registered named accumulators in GroupByContext; a hidden HAVING-only accumulator is not addressable from either.
      • HAVING with aggregates needs a two-phase approach: $group must be emitted before $match, but HAVING has to be scanned first to know which accumulators to add.

      Acceptance criteria

      • All standard aggregate functions (COUNT, SUM, AVG, MIN, MAX) are supported in the SELECT list of a grouped query.
      • Aggregate functions in ORDER BY resolve to their accumulator field without re-computation.
      • Aggregate functions in HAVING that do not appear in SELECT are computed as hidden accumulators and are absent from the result.
      • An aggregate function shared between HAVING and SELECT reuses the same accumulator, with no duplication in $group.
      • Expressions wrapping aggregates (for example AVG + 1) are supported: the accumulator is registered for the inner aggregate and the outer arithmetic is resolved in $project.
      • Non-aggregate, non-grouped columns in SELECT still throw FeatureNotSupportedException.
      • Integration tests cover each aggregate function individually and in combination, plus HAVING aggregate only, HAVING and SELECT with the same and with different functions, HAVING with an expression wrapping an aggregate, and HAVING with ORDER BY.

            Assignee:
            Almas Abdrazak
            Reporter:
            Slav Babanin
            None
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: