Dela via


Aggregera data med GraphQL i Data API Builder

Data API Builder (DAB) stöder GraphQL-sammansättning och gruppering för SQL-familjedatabaser och Azure Synapse Analytics (dedikerad SQL-pool). Med sammansättningar kan du sammanfatta numeriska fält och gruppresultat utan att skriva anpassad API-kod. Sammansättning och groupBy är inte tillgängliga för Azure Cosmos DB för NoSQL, PostgreSQL eller MySQL.

Förutsättningar

  • Databas som stöds:
    • SQL Server 2016 eller senare
    • Azure SQL Database
    • Hanterad instans i Azure SQL
    • Microsoft Fabric SQL
    • Azure Synapse Analytics (endast dedikerad SQL-pool)
  • Data-API-byggarens CLI. Installera CLI
  • En DAB-konfigurationsfil med din entitet exponerad via GraphQL.
  • En GraphQL-klient (till exempel Banana Cake Pop eller GraphQL Playground) för att köra frågor.

Databaser som stöds

Databas Sammansättningsstöd
SQL Server/Azure SQL/Microsoft Fabric SQL ✅ Ja
Azure Synapse (dedikerad SQL-pool) ✅ Ja
Azure Synapse (serverlös SQL-pool) ❌ Nej
PostgreSQL ❌ Nej
MySQL ❌ Nej
Azure Cosmos DB för NoSQL ❌ Nej

Aggregatfunktioner

DAB har stöd för följande mängdfunktioner:

Funktion Gäller för Description
sum Endast numeriska fält Summa för alla värden
average Endast numeriska fält Medelvärde för alla värden
min Endast numeriska fält Minsta värde
max Endast numeriska fält Maximalt värde
count Valfritt fält Antal värden som inte är null

Constraints

  • sum, average, minoch max fungerar bara med numeriska datatyper (int, decimal, float osv.).
  • count fungerar på alla datatyper, inklusive strängar och datum.
  • Om en tabell inte har några numeriska kolumner genererar DAB inte aggregeringsnoder för den entiteten. Du kan fortfarande använda count på icke-numeriska fält.

Valfria modifierare

Modifikator Avsikt Example
distinct: true Räkna endast unika värden Räkna distinkta kunder
having: { ... } Filtrera grupper efter aggregering Visa grupper med summan > 1 000

Kör DAB-runtime

Starta DAB med konfigurationsfilen så att GraphQL-slutpunkten är tillgänglig.

dab start

Fråga aggregerade resultat

Det här avsnittet går igenom ett fullständigt exempel som visar tabellschemat, GraphQL-frågan, genererade SQL- och JSON-svar.

Tabellschema

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

GraphQL-fråga

Använd GraphQL för att gruppera rader och returnera aggregeringsvärden för numeriska fält.

{
  books(
    groupBy: { fields: ["year"] }
  ) {
    items {
      year
    }
    aggregates {
      pages {
        sum
        average
        min
        max
      }
    }
  }
}
  • groupBy.fields grupperar rader efter de angivna kolumnerna.
  • aggregates exponerar mängdfunktioner för numeriska fält (till exempel pages).
  • GraphQL-schemat exponerar endast aggregeringar för fält som stöder dem. använd schema-introspektion i klienten för att bekräfta tillgängliga aggregeringsfält och funktioner.

Genererad SQL

DAB översätter GraphQL-frågan till 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-svar

{
  "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 }
        ]
      }
    }
  }
}

Matriserna items och aggregates justeras efter index – det första elementet i aggregates.pages motsvarar den första gruppen i items.

Aggregera utan gruppering

Beräkna aggregeringar över alla rader när du utelämnar groupBy.

GraphQL-fråga

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

Genererad 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-svar

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

Utan groupByreturnerar svaret ett enskilt objekt (inte en matris) eftersom alla rader komprimeras till ett resultat.

Gruppera efter ett eller flera fält

Gruppera rader efter en eller flera kolumner och returnera aggregeringar per grupp.

Tabellschema

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

GraphQL-fråga

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

Genererad 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-svar

{
  "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 }
        ]
      }
    }
  }
}

Svaret returnerar matriser för items och aggregerar i samma ordning så att du kan justera grupper med deras aggregerade värden.

måste filtrera aggregerade resultat

Använd having för att filtrera grupper efter aggregering. Detta motsvarar SQL-satsen HAVING .

Tabellschema

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

GraphQL-fråga

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

Genererad 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-svar

Endast kategorier där summan överstiger 10000 returneras:

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

HAVING-operatorer

Operator SQL-motsvarighet 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 }

Anmärkning

Varje having filter gäller oberoende av dess aggregerade funktion. Du kan inte skapa korsaggregeringsvillkor som "sum > 1000 OR count < 10" i en enda GraphQL-fråga.

DISTINCT i sammansättningar

Räkna unika värden med distinct: true.

Tabellschema

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

GraphQL-fråga

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

Genererad 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-svar

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

Den första count (med distinct: true) returnerar unika produkter per kund. Den andra count returnerar totala ordrar.

Anmärkning

När du begär flera aggregeringar i samma fält returnerar DAB dem i den begärda ordningen. Använd alias (till exempel uniqueProducts: count(distinct: true)) för att göra svar självdokumenterande.

Kombinera filter med aggregering

Använd filter på rader före gruppering och having för grupper efter aggregering. Det är viktigt att förstå ordningen på åtgärder:

  1. Filter (SQL WHERE) tar bort rader före gruppering
  2. Gruppera samlar återstående rader i grupper
  3. Aggregering beräknar summa, genomsnitt, min, max, antal per grupp
  4. Med tar bort grupper som inte matchar villkoret

GraphQL-fråga

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

Genererad 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

Tips/Råd

Använd filter för att exkludera rader före aggregering. Använd having för att filtrera grupper efter aggregering.

Använd alias med aggregeringar

Skapa meningsfulla fältnamn med hjälp av GraphQL-alias.

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

Schema-introspektion

Använd introspektion för att se vilka aggregeringar som är tillgängliga för en entitet.

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

Numeriska fält exponerar sum, average, min, maxoch count. Icke-numeriska fält exponerar count.

Tips och begränsningar

  • Aggregering och groupBy, tillämpas endast på SQL Server, Azure SQL, Microsoft Fabric SQL och Azure Synapse Dedicated SQL-pool.
  • Aggregeringar körs på numeriska fält. count fungerar på alla fält. Tabeller utan numeriska kolumner exponerar bara count.
  • Gruppering gäller för fält på samma entitet (ingen grupp mellan entiteterBy).
  • Stora aggregeringar kan vara dyra. indexera dina groupBy-kolumner och filtrera rader innan du grupperar när det är möjligt.
  • Skapa index för kolumner som används groupBy ofta för att förbättra frågeprestanda.

Felsökning

Fel: Fältet stöder inte aggregering

Orsak: Använda sum, average, mineller max i ett icke-numeriskt fält.

Lösning:

  • Använd schema-introspektion för att verifiera fälttyper.
  • Används count för icke-numeriska fält.
  • Kontrollera fältmappningar om du använder anpassade fältnamn.

Fel: Det gick inte att hitta aggregeringsnoder

Orsak: Entiteten har inga numeriska kolumner.

Lösning:

  • Kontrollera att tabellschemat har minst en numerisk kolumn.
  • Använd count aggregeringar på icke-numeriska fält om det behövs.

Långsamma aggregeringsfrågor

Orsak: Stora tabeller utan rätt index.

Lösning:

  • Skapa index för groupBy kolumner.
  • Använd filter för att begränsa rader före aggregering.
  • Använd having för att minska antalet returnerade grupper.

Nästa steg