Sdílet prostřednictvím


Agregace dat pomocí GraphQL v Tvůrci rozhraní Data API

Data API builder (DAB) podporuje agregaci a seskupení GraphQL pro databáze řady SQL a Azure Synapse Analytics (Dedicated SQL pool). Agregace umožňují shrnout číselná pole a výsledky seskupení bez psaní vlastního kódu rozhraní API. Agregace a groupBy nejsou k dispozici pro Azure Cosmos DB for NoSQL, PostgreSQL nebo MySQL.

Požadavky

  • Podporovaná databáze:
    • SQL Server 2016 nebo novější
    • Azure SQL Database
    • Azure SQL Managed Instance
    • Microsoft Fabric SQL
    • Azure Synapse Analytics (pouze vyhrazený fond pro zpracování SQL dotazů)
  • Rozhraní příkazového řádku pro tvorbu API dat. Instalace rozhraní příkazového řádku
  • Konfigurační soubor DAB s entitou vystavenou prostřednictvím GraphQL.
  • Klient GraphQL (například Banana Cake Pop nebo GraphQL Playground) ke spouštění dotazů.

Podporované databáze

Databáze Podpora agregace
SQL Server / Azure SQL / Microsoft Fabric SQL ✅ Ano
Azure Synapse (vyhrazená skupina SQL) ✅ Ano
Azure Synapse (bezserverová SQL služba) ❌ Ne
PostgreSQL ❌ Ne
MySQL ❌ Ne
Azure Cosmos DB for NoSQL ❌ Ne

Agregační funkce

DAB podporuje následující agregační funkce:

Funkce Vztahuje se na Description
sum Pouze číselná pole Součet všech hodnot
average Pouze číselná pole Střední hodnota všech hodnot
min Pouze číselná pole Minimální hodnota
max Pouze číselná pole Maximální hodnota
count Libovolné pole Počet hodnot, které nejsou null

Constraints

  • sum, average, mina max pracovat pouze na číselných datových typech (int, decimal, float atd.).
  • count funguje na libovolném datovém typu, včetně řetězců a kalendářních dat.
  • Pokud tabulka neobsahuje žádné číselné sloupce, DAB pro danou entitu negeneruje agregační uzly. Stále můžete použít count pro nečíselná pole.

Volitelné modifikátory

Modifikátor Účel Example
distinct: true Počítat pouze jedinečné hodnoty Počet jedinečných zákazníků
having: { ... } Filtrování skupin po agregaci Zobrazit skupiny se součtem > 1000

Spuštění modulu runtime DAB

Spusťte DAB s konfiguračním souborem, aby byl dostupný koncový bod GraphQL.

dab start

Agregované výsledky dotazu

Tato část vás provede úplným příkladem znázorňující schéma tabulky, dotaz GraphQL, vygenerovaný SQL a odpověď JSON.

Schéma tabulky

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

Dotaz GraphQL

Pomocí GraphQL seskupíte řádky a vrátíte agregační hodnoty pro číselná pole.

{
  books(
    groupBy: { fields: ["year"] }
  ) {
    items {
      year
    }
    aggregates {
      pages {
        sum
        average
        min
        max
      }
    }
  }
}
  • groupBy.fields seskupí řádky podle zadaných sloupců.
  • aggregates zveřejňuje agregační funkce pro číselná pole (například pages).
  • Schéma GraphQL zveřejňuje agregace pouze pro pole, která je podporují; Pomocí introspekce schématu v klientovi potvrďte dostupná agregovaná pole a funkce.

Vygenerovaný SQL

DAB přeloží dotaz GraphQL na 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

Odpověď JSON

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

Pole items a aggregates jsou zarovnaná podle indexu – první prvek v aggregates.pages odpovídá první skupině v items.

Agregace bez seskupení

Výpočet agregací napříč všemi řádky při vynechání groupBy.

Dotaz GraphQL

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

Vygenerovaný 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

Odpověď JSON

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

Bez groupBy se odpověď vrátí jako jeden objekt (nikoli pole), protože všechny řádky se sloučí do jednoho výsledku.

Seskupování podle jednoho nebo více polí

Seskupí řádky podle jednoho nebo více sloupců a vrátí agregace po skupinách.

Schéma tabulky

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

Dotaz GraphQL

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

Vygenerovaný 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

Odpověď JSON

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

Odpověď vrátí pole pro items a agregace ve stejném pořadí, abyste mohli zarovnat skupiny s jejich agregovanými hodnotami.

Nutnost filtrování agregovaných výsledků

Slouží having k filtrování skupin po agregaci. Je to ekvivalent klauzule HAVING SQL.

Schéma tabulky

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

Dotaz GraphQL

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

Vygenerovaný 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

Odpověď JSON

Vrátí se pouze kategorie, ve kterých je součet větší než 1 0000:

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

Operátory HAVING

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

Poznámka:

Každý having filtr platí nezávisle na své agregační funkci. V jednom dotazu GraphQL nemůžete vytvořit křížové agregační podmínky, jako je součet > 1000 NEBO < 10.

DISTINCT v agregacích

Spočítejte jedinečné hodnoty pomocí distinct: true.

Schéma tabulky

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

Dotaz GraphQL

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

Vygenerovaný 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

Odpověď JSON

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

První count (s distinct: true) vrátí jedinečné produkty pro každého zákazníka. Druhá count vrátí celkové objednávky.

Poznámka:

Při vyžádání více agregací u stejného pole je DAB vrátí v požadovaném pořadí. K samodokumentování odpovědí použijte aliasy (například uniqueProducts: count(distinct: true)).

Kombinování filtrů s agregací

Platí filter pro řádky před seskupením a having pro skupiny po agregaci. Pochopení pořadí operací je důležité:

  1. Filtr (SQL WHERE) odebere řádky před seskupením.
  2. Seskupí zbývající řádky do skupin.
  3. Agregace vypočítá součet, průměr, minimum, maximum a počet pro každou skupinu.
  4. Podmínka HAVING odstraňuje skupiny, které neodpovídají podmínce

Dotaz GraphQL

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

Vygenerovaný 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

Návod

Slouží filter k vyloučení řádků před agregací. Slouží having k filtrování skupin po agregaci.

Použití aliasů s agregacemi

Vytvářejte smysluplné názvy polí pomocí aliasů GraphQL.

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

Introspekce schématu

Pomocí introspekce můžete zjistit, které agregace jsou pro entitu k dispozici.

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

Číselná pole zpřístupňují sum, average, min, max, a count. Nečíselná pole zpřístupňují count.

Tipy a omezení

  • Agregace a groupBy se vztahuje pouze na SQL Server, Azure SQL, Microsoft Fabric SQL a vyhrazený SQL fond Azure Synapse.
  • Agregace se spouštějí na číselných polích; count pracuje na libovolném poli. Tabulky bez číselných sloupců zpřístupňují pouze count.
  • Seskupení platí pro pole v rámci téže entity (bez možnosti groupBy napříč entitami).
  • Velké agregace mohou být nákladné; indexujte sloupce groupBy a vyfiltrujte řádky před seskupením, pokud je to možné.
  • Vytváření indexů u často používaných groupBy sloupců za účelem zlepšení výkonu dotazů

Řešení problémů

Chyba: Pole nepodporuje agregaci

Příčina: Použití sum, average, minnebo max v nečíselném poli

Řešení:

  • Pomocí introspekce schématu ověřte typy polí.
  • Slouží count pro nečíselná pole.
  • Zkontrolujte mapování polí, pokud používáte vlastní názvy polí.

Chyba: Agregační uzly se nenašly

Příčina: Entita nemá žádné číselné sloupce.

Řešení:

  • Ověřte, že schéma tabulky obsahuje alespoň jeden číselný sloupec.
  • V případě potřeby používejte count agregace pro nečíselná pole.

Pomalé agregační dotazy

Příčina: Velké tabulky bez správných indexů

Řešení:

  • Vytváření indexů ve groupBy sloupcích
  • Slouží filter k omezení řádků před agregací.
  • Použijte having ke snížení počtu vrácených skupin.

Další krok