Delen via


Gegevens aggregeren met GraphQL in Data API Builder

Data API Builder (DAB) ondersteunt GraphQL-aggregatie en groepering voor SQL-familiedatabases en Azure Synapse Analytics (toegewezen SQL-pool). Met aggregaties kunt u numerieke velden en groepsresultaten samenvatten zonder aangepaste API-code te schrijven. Aggregatie en groupBy zijn niet beschikbaar voor Azure Cosmos DB for NoSQL, PostgreSQL of MySQL.

Vereiste voorwaarden

  • Ondersteunde database:
    • SQL Server 2016 of hoger
    • Azure SQL Database
    • Azure SQL Managed Instance (een beheerde database-instantie van Azure)
    • Microsoft Fabric SQL
    • Azure Synapse Analytics (alleen toegewezen SQL-pool)
  • Data-API-bouwer CLI. De CLI installeren
  • Een DAB-configuratiebestand met uw entiteit die beschikbaar is via GraphQL.
  • Een GraphQL-client (bijvoorbeeld Banana Cake Pop of GraphQL Playground) om query's uit te voeren.

Ondersteunde databases

gegevensbank Ondersteuning voor aggregatie
SQL Server/Azure SQL/Microsoft Fabric SQL ✅ Ja
Azure Synapse (toegewezen SQL-pool) ✅ Ja
Azure Synapse (serverloze SQL-pool) ❌ Nee
PostgreSQL ❌ Nee
MySQL ❌ Nee
Azure Cosmos DB voor NoSQL ❌ Nee

Gecompileerde functies

DAB ondersteunt de volgende statistische functies:

Functie Van toepassing op: Description
sum Alleen numerieke velden Totaal van alle waarden
average Alleen numerieke velden Gemiddelde van alle waarden
min Alleen numerieke velden Minimumwaarde
max Alleen numerieke velden Maximale waarde
count Elk willekeurig veld Aantal niet-null-waarden

Constraints

  • sum, average, minen max werkt alleen aan numerieke gegevenstypen (int, decimaal, float, enzovoort).
  • count werkt op elk gegevenstype, inclusief tekenreeksen en datums.
  • Als een tabel geen numerieke kolommen heeft, genereert DAB geen aggregatieknooppunten voor die entiteit. U kunt nog steeds count gebruiken voor niet-numerieke velden.

Optionele modifiers

Aanpasser Purpose Example
distinct: true Alleen unieke waarden tellen Unieke klanten tellen
having: { ... } Filteren van groepen na aggregatie Groepen weergeven met de som > 1000

De DAB-runtime uitvoeren

Start DAB met uw configuratiebestand, zodat het GraphQL-eindpunt beschikbaar is.

dab start

Geaggregeerde resultaten van query's

In deze sectie wordt een volledig voorbeeld beschreven met het tabelschema, de GraphQL-query, het gegenereerde SQL- en JSON-antwoord.

Tabelschema

CREATE TABLE books (
    id INT PRIMARY KEY,
    title NVARCHAR(200),
    year INT,
    pages INT
);

GraphQL-query

Gebruik GraphQL om rijen te groeperen en geaggregeerde waarden te retourneren voor numerieke velden.

{
  books(
    groupBy: { fields: ["year"] }
  ) {
    items {
      year
    }
    aggregates {
      pages {
        sum
        average
        min
        max
      }
    }
  }
}
  • groupBy.fields groepeert rijen op basis van de opgegeven kolommen.
  • aggregates maakt statistische functies beschikbaar voor numerieke velden (bijvoorbeeld pages).
  • Het GraphQL-schema maakt alleen aggregaties beschikbaar voor velden die deze ondersteunen; gebruik schema-introspectie in uw client om beschikbare statistische velden en functies te bevestigen.

Gegenereerde SQL

DAB vertaalt de GraphQL-query in T-SQL:

SELECT 
    [year],
    SUM([pages]) AS [sum],
    AVG([pages]) AS [average],
    MIN([pages]) AS [min],
    MAX([pages]) AS [max]
FROM [dbo].[books]
GROUP BY [year]
FOR JSON PATH, INCLUDE_NULL_VALUES

JSON-antwoord

{
  "data": {
    "books": {
      "items": [
        { "year": 2023 },
        { "year": 2024 }
      ],
      "aggregates": {
        "pages": [
          { "sum": 3200, "average": 320, "min": 120, "max": 450 },
          { "sum": 4500, "average": 300, "min": 140, "max": 510 }
        ]
      }
    }
  }
}

De items en aggregates arrays worden uitgelijnd op index—het eerste element in aggregates.pages komt overeen met de eerste groep in items.

Aggregeren zonder groepering

Aggregaties berekenen voor alle rijen wanneer u weglaat groupBy.

GraphQL-query

{
  books {
    aggregates {
      pages {
        sum
        average
        min
        max
        count
      }
      id {
        count
      }
    }
  }
}

Gegenereerde SQL

SELECT
    SUM([pages]) AS [sum],
    AVG([pages]) AS [average],
    MIN([pages]) AS [min],
    MAX([pages]) AS [max],
    COUNT([pages]) AS [count],
    COUNT([id]) AS [count]
FROM [dbo].[books]
FOR JSON PATH, INCLUDE_NULL_VALUES

JSON-antwoord

{
  "data": {
    "books": {
      "aggregates": {
        "pages": {
          "sum": 15420,
          "average": 308,
          "min": 120,
          "max": 850,
          "count": 50
        },
        "id": {
          "count": 50
        }
      }
    }
  }
}

Zonder groupBy, retourneert het antwoord één object (geen matrix), omdat alle rijen samenvouwen tot één resultaat.

Groeperen op een of meer velden

Groepeer rijen op een of meer kolommen en geef aggregaties per groep terug.

Tabelschema

CREATE TABLE sales (
    id INT PRIMARY KEY,
    year INT,
    category NVARCHAR(50),
    revenue DECIMAL(10,2),
    quantity INT
);

GraphQL-query

{
  sales(
    groupBy: { fields: ["year", "category"] }
  ) {
    items {
      year
      category
    }
    aggregates {
      revenue {
        sum
        average
      }
      quantity {
        sum
      }
    }
  }
}

Gegenereerde SQL

SELECT
    [year],
    [category],
    SUM([revenue]) AS [sum],
    AVG([revenue]) AS [average],
    SUM([quantity]) AS [sum]
FROM [dbo].[sales]
GROUP BY [year], [category]
FOR JSON PATH, INCLUDE_NULL_VALUES

JSON-antwoord

{
  "data": {
    "sales": {
      "items": [
        { "year": 2023, "category": "Books" },
        { "year": 2023, "category": "Electronics" },
        { "year": 2024, "category": "Books" }
      ],
      "aggregates": {
        "revenue": [
          { "sum": 45000.00, "average": 150.00 },
          { "sum": 120000.00, "average": 600.00 },
          { "sum": 52000.00, "average": 173.33 }
        ],
        "quantity": [
          { "sum": 300 },
          { "sum": 200 },
          { "sum": 300 }
        ]
      }
    }
  }
}

Het antwoord retourneert matrices voor items en aggregaties in dezelfde volgorde, zodat u groepen kunt uitlijnen met hun geaggregeerde waarden.

HET FILTEREN van geaggregeerde resultaten

Gebruik having dit om groepen te filteren na aggregatie. Dit komt overeen met de component van HAVING SQL.

Tabelschema

CREATE TABLE products (
    id INT PRIMARY KEY,
    category NVARCHAR(50),
    price DECIMAL(10,2)
);

GraphQL-query

{
  products(
    groupBy: { fields: ["category"] }
  ) {
    items { category }
    aggregates {
      price {
        sum(having: { gt: 10000 })
        average
      }
    }
  }
}

Gegenereerde SQL

SELECT
    [category],
    SUM([price]) AS [sum],
    AVG([price]) AS [average]
FROM [dbo].[products]
GROUP BY [category]
HAVING SUM([price]) > 10000
FOR JSON PATH, INCLUDE_NULL_VALUES

JSON-antwoord

Alleen categorieën waarbij de som groter is dan 10000 worden geretourneerd:

{
  "data": {
    "products": {
      "items": [
        { "category": "Electronics" },
        { "category": "Furniture" }
      ],
      "aggregates": {
        "price": [
          { "sum": 15000.00, "average": 300.00 },
          { "sum": 12000.00, "average": 400.00 }
        ]
      }
    }
  }
}

HAVING-operators

Operator SQL-equivalent Example
eq = having: { eq: 100 }
neq <> having: { neq: 0 }
gt > having: { gt: 1000 }
gte >= having: { gte: 500 }
lt < having: { lt: 100 }
lte <= having: { lte: 50 }

Opmerking

Elk having filter wordt onafhankelijk toegepast op zijn aggregatiefunctie. U kunt geen voorwaarden voor kruisaggregaties maken, zoals 'som > 1000 OF aantal < 10' in één GraphQL-query.

DISTINCT in aggregaties

Unieke waarden tellen met distinct: true.

Tabelschema

CREATE TABLE orders (
    id INT PRIMARY KEY,
    customer_id INT,
    product_id INT
);

GraphQL-query

{
  orders(
    groupBy: { fields: ["customer_id"] }
  ) {
    items { customer_id }
    aggregates {
      product_id {
        count(distinct: true)
        count
      }
    }
  }
}

Gegenereerde SQL

SELECT
    [customer_id],
    COUNT(DISTINCT [product_id]) AS [count],
    COUNT([product_id]) AS [count]
FROM [dbo].[orders]
GROUP BY [customer_id]
FOR JSON PATH, INCLUDE_NULL_VALUES

JSON-antwoord

{
  "data": {
    "orders": {
      "items": [
        { "customer_id": 101 },
        { "customer_id": 102 }
      ],
      "aggregates": {
        "product_id": [
          { "count": 5 },
          { "count": 3 }
        ]
      }
    }
  }
}

De eerste count (met distinct: true) retourneert unieke producten per klant. De tweede count retourneert totale bestellingen.

Opmerking

Wanneer u meerdere aggregaties op hetzelfde veld aanvraagt, retourneert DAB deze in de aangevraagde volgorde. Gebruik aliassen (bijvoorbeeld uniqueProducts: count(distinct: true)) om antwoorden zelfdocumenterend te maken.

Filters combineren met aggregatie

Toepassen filter op rijen voordat u groepeert en having op groepen na aggregatie. Inzicht in de volgorde van bewerkingen is essentieel:

  1. Met filter (SQL WHERE) worden rijen verwijderd voordat u groepeert
  2. Groeperen groepeert de resterende rijen in groepen
  3. Aggregaat berekent sum/avg/min/max/count per groep
  4. De Having-clausule verwijdert groepen die niet aan de voorwaarde voldoen

GraphQL-query

{
  sales(
    filter: { year: { gte: 2023 } }
    groupBy: { fields: ["region"] }
  ) {
    items { region }
    aggregates {
      revenue { sum average }
    }
  }
}

Gegenereerde SQL

SELECT
    [region],
    SUM([revenue]) AS [sum],
    AVG([revenue]) AS [average]
FROM [dbo].[sales]
WHERE [year] >= 2023
GROUP BY [region]
FOR JSON PATH, INCLUDE_NULL_VALUES

Aanbeveling

Gebruik filter dit om rijen uit te sluiten vóór aggregatie. Gebruik having dit om groepen te filteren na aggregatie.

Aliassen gebruiken met aggregaties

Maak betekenisvolle veldnamen met Behulp van GraphQL-aliassen.

{
  products(
    groupBy: { fields: ["category"] }
  ) {
    items { category }
    aggregates {
      price {
        totalRevenue: sum
        avgPrice: average
        cheapest: min
        mostExpensive: max
        productCount: count
      }
    }
  }
}

Schema-introspectie

Gebruik introspectie om te zien welke aggregaties beschikbaar zijn voor een entiteit.

{
  __type(name: "BooksAggregates") {
    fields {
      name
      type { name }
    }
  }
}

Numerieke velden worden weergegevensum, average, , min, en maxcount. Niet-numerieke velden openbaren count.

Tips en beperkingen

  • Aggregatie en groupBy zijn van toepassing op SQL Server, Azure SQL, Microsoft Fabric SQL en Azure Synapse Dedicated SQL-pool.
  • Aggregaties worden uitgevoerd op numerieke velden; count werkt op elk veld. Tabellen zonder numerieke kolommen tonen alleen count.
  • Groeperen is van toepassing op velden op dezelfde entiteit (geen cross-entity groupBy).
  • Grote aggregaties kunnen duur zijn; indexeer uw groupBy-kolommen en filter rijen voordat u deze indien mogelijk groepeert.
  • Indexen maken voor veelgebruikte groupBy kolommen om de queryprestaties te verbeteren.

Probleemoplossingsproces

Fout: Veld biedt geen ondersteuning voor aggregatie

Oorzaak: Het gebruik van sum, average, min, of max op een niet-numeriek veld.

Solution:

  • Gebruik schema-introspectie om veldtypen te verifiëren.
  • Gebruiken count voor niet-numerieke velden.
  • Controleer veldtoewijzingen als u aangepaste veldnamen gebruikt.

Fout: Aggregatieknooppunten zijn niet gevonden

Oorzaak: de entiteit heeft geen numerieke kolommen.

Solution:

  • Controleer of het tabelschema ten minste één numerieke kolom bevat.
  • Gebruik count indien nodig aggregaties voor niet-numerieke velden.

Trage aggregatiequeries

Oorzaak: Grote tabellen zonder de juiste indexen.

Solution:

  • Indexen maken voor groupBy kolommen.
  • Gebruik filter om de rijen te beperken voordat er aggregatie plaatsvindt.
  • Gebruik having dit om het aantal geretourneerde groepen te verminderen.

Volgende stap