Aggregera data med GraphQL

Data API Builder stöder GraphQL-aggregering för SQL Server familj och Azure Synapse Analytics dedikerade SQL-poolentiteter. Använd fältet i groupBy en samlingsfråga för att beräkna sum, avg, min, maxoch count värden.

Exemplen i den här artikeln använder SQL Server- och GraphQL-entiteter med läsbehörighet. Data API Builder genererar SQL-satser som de som visas i varje scenario. Parametervärden visas som frågeparametrar vid körning. Funktionerna sum, avg, minoch max gäller för numeriska fält. Funktionen count fungerar på alla fält.

Important

Sammansättning är inte tillgängligt för Azure Cosmos DB för NoSQL, PostgreSQL eller MySQL.

Sammansättning är aktiverat som standard. Om du vill inaktivera det anger du enable-aggregation till false under runtime.graphql i konfigurationsfilen. Sammansättningsfrågor returnerar en sida med grupper, 100 som standard. first Använd argumentet i samlingsfrågan för att ändra maxvärdet, till exempel books(first: 500). Ange standardvärdet med runtime.pagination.default-page-size.

GraphQL-schematillägg

När du aktiverar aggregering lägger Data API Builder till aggregeringsfält och genererade typer i varje GraphQL-samling som stöds. De exakta genererade typnamnen är entitetsspecifika och synliga via GraphQL-introspektion, men frågesyntaxen är konsekvent mellan entiteter.

Följande kodfragment visar syntaxformat, inte fullständiga GraphQL-frågor.

groupBy

Returnerar grupperade rader för samlingen. Välj den här medlemmen i stället items för i en aggregeringsfråga.

<collection> { groupBy { ... } }

groupBy(fields: [...])

Visar de entitetsfält som ska grupperas efter. fields Utelämna för att aggregera alla rader i en grupp.

<collection> { groupBy(fields: [<field>, ...]) { ... } }

fields

Returnerar de grupperade fältvärdena för varje rad i aggregeringsresultatet.

groupBy(fields: [<field>]) { fields { <field> } }

aggregations

Innehåller de aggregerade funktionsvalen för varje grupp.

groupBy { aggregations { <alias>: <function>(field: <field>) } }

sum, avg, minoch max

Aggregera numeriska fält.

aggregations { <alias>: sum(field: <numeric-field>) }
aggregations { <alias>: avg(field: <numeric-field>) }
aggregations { <alias>: min(field: <numeric-field>) }
aggregations { <alias>: max(field: <numeric-field>) }

count

Räknar värden för ett fält.

aggregations { <alias>: count(field: <field>) }

field

Identifierar det entitetsfält som ska aggregeras. Fältnamn är uppräkningsvärden, inte strängar.

<function>(field: <field>)

having

Filtrerar grupper efter att Data API Builder beräknar det aggregerade värdet.

aggregations { <alias>: <function>(field: <field>, having: { <operator>: <value> }) }

distinct

Räknar unika värden när det används med count.

aggregations { <alias>: count(field: <field>, distinct: true) }

Data API builder genererar entitetsspecifika GraphQL-typer för dessa medlemmar, inklusive grupperade radtyper, grupperade fälttyper, aggregerade urvalstyper, fältenumerationer och having-indatatyper. Du behöver inte namnge de genererade typerna i en fråga.

Samples

Följande exempel visar SQL-tabellen, GraphQL-frågan, resulterande SQL och resulterande utdata för vanliga aggregeringsmönster.

Aggregera alla rader i en tabell

Använd det här mönstret när du vill ha en sammanfattningsrad för hela entiteten.

SQL-tabell

CREATE TABLE dbo.Books (
    id INT NOT NULL PRIMARY KEY,
    title NVARCHAR(200) NOT NULL,
    [year] INT NOT NULL,
    pages INT NOT NULL
);

INSERT INTO dbo.Books (id, title, [year], pages) VALUES
    (1, N'GraphQL Basics', 2023, 120),
    (2, N'Advanced APIs', 2023, 450),
    (3, N'Data Patterns', 2023, 390),
    (4, N'Cloud APIs', 2024, 140),
    (5, N'Runtime Internals', 2024, 510),
    (6, N'Query Tuning', 2024, 250);
id title år Sidor
1 Grunderna i GraphQL 2023 120
2 Avancerade API:er 2023 450
3 Datamönster 2023 390
4 Moln-API:er 2024 140
5 Interna funktioner i körmiljön 2024 510
6 Frågeoptimering 2024 250

GraphQL-fråga

{
  books {
    groupBy {
      aggregations {
        totalPages: sum(field: pages)
        averagePages: avg(field: pages)
        shortestBook: min(field: pages)
        longestBook: max(field: pages)
        bookCount: count(field: id)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
    SUM([table0].[pages]) AS [totalPages],
    AVG([table0].[pages]) AS [averagePages],
    MIN([table0].[pages]) AS [shortestBook],
    MAX([table0].[pages]) AS [longestBook],
    COUNT([table0].[id]) AS [bookCount]
FROM [dbo].[Books] AS [table0]
WHERE 1 = 1
FOR JSON PATH, INCLUDE_NULL_VALUES;

Resulterande utdata

{
  "data": {
    "books": {
      "groupBy": [
        {
          "aggregations": {
            "totalPages": 1860,
            "averagePages": 310,
            "shortestBook": 120,
            "longestBook": 510,
            "bookCount": 6
          }
        }
      ]
    }
  }
}
totalPages genomsnittligt antal sidor shortestBook longestBook bookCount
1860 310 120 510 6

Gruppera rader efter ett fält

Använd groupBy(fields: [...]) för att returnera en aggregeringsrad per fältvärde. Fältnamn är GraphQL-uppräkningsvärden, inte strängar.

SQL-tabell

CREATE TABLE dbo.Books (
  id INT NOT NULL PRIMARY KEY,
  title NVARCHAR(200) NOT NULL,
  [year] INT NOT NULL,
  pages INT NOT NULL
);

INSERT INTO dbo.Books (id, title, [year], pages) VALUES
  (1, N'GraphQL Basics', 2023, 120),
  (2, N'Advanced APIs', 2023, 450),
  (3, N'Data Patterns', 2023, 390),
  (4, N'Cloud APIs', 2024, 140),
  (5, N'Runtime Internals', 2024, 510),
  (6, N'Query Tuning', 2024, 250);
id title år Sidor
1 Grunderna i GraphQL 2023 120
2 Avancerade API:er 2023 450
3 Datamönster 2023 390
4 Moln-API:er 2024 140
5 Interna funktioner i körmiljön 2024 510
6 Frågeoptimering 2024 250

GraphQL-fråga

{
  books(orderBy: { year: ASC }) {
    groupBy(fields: [year]) {
      fields { year }
      aggregations {
        totalPages: sum(field: pages)
        averagePages: avg(field: pages)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
    [table0].[year] AS [year],
    SUM([table0].[pages]) AS [totalPages],
    AVG([table0].[pages]) AS [averagePages]
FROM [dbo].[Books] AS [table0]
WHERE 1 = 1
GROUP BY [table0].[year]
ORDER BY [table0].[year] ASC
FOR JSON PATH, INCLUDE_NULL_VALUES;

Resulterande utdata

{
  "data": {
    "books": {
      "groupBy": [
        {
          "fields": {
            "year": 2023
          },
          "aggregations": {
            "totalPages": 960,
            "averagePages": 320
          }
        },
        {
          "fields": {
            "year": 2024
          },
          "aggregations": {
            "totalPages": 900,
            "averagePages": 300
          }
        }
      ]
    }
  }
}
år totalPages genomsnittligt antal sidor
2023 960 320
2024 900 300

Gruppera rader från en vy

Sammansättning fungerar också för visningsbaserade entiteter. Konfigurera ett nyckelfält för vyn så att Data API-byggare kan exponera det som en entitet.

SQL-view

CREATE TABLE dbo.Employees (
  id INT NOT NULL PRIMARY KEY,
  name NVARCHAR(100) NOT NULL,
  department NVARCHAR(50) NOT NULL,
  title NVARCHAR(100) NOT NULL,
  age INT NOT NULL
);

INSERT INTO dbo.Employees (id, name, department, title, age) VALUES
  (1, N'Ada', N'Engineering', N'Developer', 29),
  (2, N'Ben', N'Engineering', N'Architect', 41),
  (3, N'Cora', N'Sales', N'Account manager', 34),
  (4, N'Diego', N'Sales', N'Sales lead', 52),
  (5, N'Ema', N'Support', N'Support engineer', 25),
  (6, N'Finn', N'Support', N'Support lead', 38),
  (7, N'Gia', N'Engineering', N'Engineering manager', 45);

CREATE VIEW dbo.EmployeeAgeReport
AS
SELECT id, department, age
FROM dbo.Employees;
id Avdelning ålder
1 Ingenjörsvetenskap 29
2 Ingenjörsvetenskap 41
3 Sales 34
4 Sales 52
5 Support 25
6 Support 38
7 Ingenjörsvetenskap 45

Konfigurera vyn med id som nyckelfält:

dab add EmployeeAgeReport --source dbo.EmployeeAgeReport --source.type view --source.key-fields id --permissions "anonymous:read"

GraphQL-fråga

{
  employeeAgeReports(orderBy: { department: ASC }) {
    groupBy(fields: [department]) {
      fields { department }
      aggregations {
        youngest: min(field: age)
        oldest: max(field: age)
        employeeCount: count(field: id)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
  [table0].[department] AS [department],
  MIN([table0].[age]) AS [youngest],
  MAX([table0].[age]) AS [oldest],
  COUNT([table0].[id]) AS [employeeCount]
FROM [dbo].[EmployeeAgeReport] AS [table0]
WHERE 1 = 1
GROUP BY [table0].[department]
ORDER BY [table0].[department] ASC
FOR JSON PATH, INCLUDE_NULL_VALUES;

Resulterande utdata

{
  "data": {
    "employeeAgeReports": {
      "groupBy": [
        {
          "fields": {
            "department": "Engineering"
          },
          "aggregations": {
            "youngest": 29,
            "oldest": 45,
            "employeeCount": 3
          }
        },
        {
          "fields": {
            "department": "Sales"
          },
          "aggregations": {
            "youngest": 34,
            "oldest": 52,
            "employeeCount": 2
          }
        },
        {
          "fields": {
            "department": "Support"
          },
          "aggregations": {
            "youngest": 25,
            "oldest": 38,
            "employeeCount": 2
          }
        }
      ]
    }
  }
}
Avdelning Yngsta Äldsta antal anställda
Ingenjörsvetenskap 29 45 3
Sales 34 52 2
Support 25 38 2

Filtrera rader före aggregering

Använd filter i samlingsfrågan för att begränsa källrader innan Data API Builder grupperar och aggregerar dem.

SQL-vy

CREATE TABLE dbo.Employees (
  id INT NOT NULL PRIMARY KEY,
  name NVARCHAR(100) NOT NULL,
  department NVARCHAR(50) NOT NULL,
  title NVARCHAR(100) NOT NULL,
  age INT NOT NULL
);

INSERT INTO dbo.Employees (id, name, department, title, age) VALUES
  (1, N'Ada', N'Engineering', N'Developer', 29),
  (2, N'Ben', N'Engineering', N'Architect', 41),
  (3, N'Cora', N'Sales', N'Account manager', 34),
  (4, N'Diego', N'Sales', N'Sales lead', 52),
  (5, N'Ema', N'Support', N'Support engineer', 25),
  (6, N'Finn', N'Support', N'Support lead', 38),
  (7, N'Gia', N'Engineering', N'Engineering manager', 45);

CREATE VIEW dbo.EmployeeAgeReport
AS
SELECT id, department, age
FROM dbo.Employees;
id Avdelning ålder
1 Ingenjörsvetenskap 29
2 Ingenjörsvetenskap 41
3 Sales 34
4 Sales 52
5 Support 25
6 Support 38
7 Ingenjörsvetenskap 45

GraphQL-fråga

{
  employeeAgeReports(filter: { age: { gt: 30 } }, orderBy: { department: ASC }) {
    groupBy(fields: [department]) {
      fields { department }
      aggregations {
        youngest: min(field: age)
        oldest: max(field: age)
        employeeCount: count(field: id)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
  [table0].[department] AS [department],
  MIN([table0].[age]) AS [youngest],
  MAX([table0].[age]) AS [oldest],
  COUNT([table0].[id]) AS [employeeCount]
FROM [dbo].[EmployeeAgeReport] AS [table0]
WHERE [table0].[age] > @param1
GROUP BY [table0].[department]
ORDER BY [table0].[department] ASC
FOR JSON PATH, INCLUDE_NULL_VALUES;

För den här frågan är @param130.

Resulterande utdata

{
  "data": {
    "employeeAgeReports": {
      "groupBy": [
        {
          "fields": {
            "department": "Engineering"
          },
          "aggregations": {
            "youngest": 41,
            "oldest": 45,
            "employeeCount": 2
          }
        },
        {
          "fields": {
            "department": "Sales"
          },
          "aggregations": {
            "youngest": 34,
            "oldest": 52,
            "employeeCount": 2
          }
        },
        {
          "fields": {
            "department": "Support"
          },
          "aggregations": {
            "youngest": 38,
            "oldest": 38,
            "employeeCount": 1
          }
        }
      ]
    }
  }
}
Avdelning Yngsta äldsta antal anställda
Ingenjörsvetenskap 41 45 2
Sales 34 52 2
Support 38 38 1

Filtrera grupper med hjälp av having

Använd having på en aggregeringsfunktion för att filtrera grupper efter aggregering. Det här mönstret mappar till en SQL-sats HAVING .

SQL-tabell

CREATE TABLE dbo.Products (
    id INT NOT NULL PRIMARY KEY,
    category NVARCHAR(50) NOT NULL,
    price DECIMAL(10,2) NOT NULL
);

INSERT INTO dbo.Products (id, category, price) VALUES
    (1, N'Electronics', 5000.00),
    (2, N'Electronics', 10000.00),
    (3, N'Furniture', 4000.00),
    (4, N'Furniture', 8000.00),
    (5, N'Books', 100.00),
    (6, N'Books', 200.00);
id category pris
1 Elektronik 5000.00
2 Elektronik 10000.00
3 Möbler 4000.00
4 Möbler 8000.00
5 Böcker 100,00
6 Böcker 200.00

GraphQL-fråga

{
  products(orderBy: { category: ASC }) {
    groupBy(fields: [category]) {
      fields { category }
      aggregations {
        totalValue: sum(field: price, having: { gt: 10000 })
        averagePrice: avg(field: price)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
    [table0].[category] AS [category],
    SUM([table0].[price]) AS [totalValue],
    AVG([table0].[price]) AS [averagePrice]
FROM [dbo].[Products] AS [table0]
WHERE 1 = 1
GROUP BY [table0].[category]
HAVING SUM([table0].[price]) > @param1
ORDER BY [table0].[category] ASC
FOR JSON PATH, INCLUDE_NULL_VALUES;

För den här frågan, @param1 är 10000.

Resulterande utdata

{
  "data": {
    "products": {
      "groupBy": [
        {
          "fields": {
            "category": "Electronics"
          },
          "aggregations": {
            "totalValue": 15000,
            "averagePrice": 7500
          }
        },
        {
          "fields": {
            "category": "Furniture"
          },
          "aggregations": {
            "totalValue": 12000,
            "averagePrice": 6000
          }
        }
      ]
    }
  }
}
category totalvärde genomsnittspris
Elektronik 15000 7500
Möbler 12000 6000

Räkna distinkta värden

Använd distinct: true med count för att räkna unika värden i varje grupp.

SQL-tabell

CREATE TABLE dbo.Orders (
    id INT NOT NULL PRIMARY KEY,
    customer_id INT NOT NULL,
    product_id INT NOT NULL
);

INSERT INTO dbo.Orders (id, customer_id, product_id) VALUES
    (1, 101, 1),
    (2, 101, 2),
    (3, 101, 2),
    (4, 101, 3),
    (5, 101, 4),
    (6, 101, 5),
    (7, 102, 1),
    (8, 102, 1),
    (9, 102, 2),
    (10, 102, 3);
id customer_id product_id
1 101 1
2 101 2
3 101 2
4 101 3
5 101 4
6 101 5
7 102 1
8 102 1
9 102 2
10 102 3

GraphQL-fråga

{
  orders(orderBy: { customer_id: ASC }) {
    groupBy(fields: [customer_id]) {
      fields { customer_id }
      aggregations {
        uniqueProducts: count(field: product_id, distinct: true)
        totalOrders: count(field: id)
      }
    }
  }
}

Genererad SQL

SELECT TOP 100
    [table0].[customer_id] AS [customer_id],
    COUNT(DISTINCT ([table0].[product_id])) AS [uniqueProducts],
    COUNT([table0].[id]) AS [totalOrders]
FROM [dbo].[Orders] AS [table0]
WHERE 1 = 1
GROUP BY [table0].[customer_id]
ORDER BY [table0].[customer_id] ASC
FOR JSON PATH, INCLUDE_NULL_VALUES;

Resulterande utdata

{
  "data": {
    "orders": {
      "groupBy": [
        {
          "fields": {
            "customer_id": 101
          },
          "aggregations": {
            "uniqueProducts": 5,
            "totalOrders": 6
          }
        },
        {
          "fields": {
            "customer_id": 102
          },
          "aggregations": {
            "uniqueProducts": 3,
            "totalOrders": 4
          }
        }
      ]
    }
  }
}
customer_id uniqueProducts Totalt antal beställningar
101 5 6
102 3 4

Vanliga misstag

  • Välj groupBy i samlingsfältet. Skicka inte groupBy som ett argument av samlingstyp.
  • Använd aggregations, inte aggregates.
  • Använd avg, inte average.
  • Använd enumvärden för fält, till exempel fields: [year]. Ange inte fältnamn.
  • Välj inte items och groupBy i samma samlingsfråga.
  • När du grupperar efter fält väljer du bara samma fält i fields objektet.