Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Data API builder поддерживает агрегацию GraphQL для сущностей семейства SQL Server и выделенного пула SQL в Azure Synapse Analytics. Используйте поле groupBy в запросе к коллекции для вычисления значений sum, avg, min, max и count.
В примерах в этой статье используются сущности SQL Server и GraphQL с разрешением на чтение. Data API builder генерирует SQL-запросы, подобные инструкциям, показанным для каждого сценария. Значения параметров отображаются в качестве параметров запроса во время выполнения. Функции sum, avgminи max функции применяются к числовым полям. Функция count работает в любом поле.
Important
Агрегирование недоступно для Azure Cosmos DB для NoSQL, PostgreSQL или MySQL.
Агрегирование по умолчанию включено. Чтобы отключить это, установите enable-aggregation в значение false в разделе runtime.graphql файла конфигурации. Запросы агрегирования возвращают одну страницу групп, 100 по умолчанию. Используйте аргумент first в запросе к коллекции, чтобы изменить максимум, например books(first: 500). Задайте значение по умолчанию runtime.pagination.default-page-size.
Дополнения схемы GraphQL
При включении агрегирования построитель api данных добавляет поля агрегирования и созданные типы в каждую поддерживаемую коллекцию GraphQL. Точные имена сгенерированных типов зависят от сущности и видны через интроспекцию GraphQL, но синтаксис запросов одинаков для всех сущностей.
Следующие фрагменты кода показывают форматы синтаксиса, а не полные запросы GraphQL.
groupBy
Возвращает сгруппированные строки для коллекции. Выберите этот элемент вместо items в агрегационном запросе.
<collection> { groupBy { ... } }
groupBy(fields: [...])
Перечисляет поля сущности, по которым выполняется группировка. Опустите fields, чтобы объединить все строки в одну группу.
<collection> { groupBy(fields: [<field>, ...]) { ... } }
fields
Возвращает сгруппированные значения полей для каждой строки в результате агрегирования.
groupBy(fields: [<field>]) { fields { <field> } }
aggregations
Содержит выбор агрегатной функции для каждой группы.
groupBy { aggregations { <alias>: <function>(field: <field>) } }
sum, avg, min и max
Агрегированные числовые поля.
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
Подсчитывает значения для поля.
aggregations { <alias>: count(field: <field>) }
field
Указывает поле сущности для агрегирования. Имена полей — это значения перечисления, а не строки.
<function>(field: <field>)
having
Фильтрует группы после того, как конструктор Data API вычисляет агрегированное значение.
aggregations { <alias>: <function>(field: <field>, having: { <operator>: <value> }) }
distinct
Подсчитывает уникальные значения при использовании с count.
aggregations { <alias>: count(field: <field>, distinct: true) }
Построитель Data API создает для этих членов специфичные для сущности типы GraphQL, включая типы строк группировки, типы сгруппированных полей, типы агрегатных выборок, перечисления полей и типы входных данных having. В запросе не нужно указывать имена этих сгенерированных типов.
Samples
В следующих примерах показана таблица SQL, запрос GraphQL, результирующий SQL и результирующий результат для распространенных шаблонов агрегирования.
Агрегировать все строки в таблице
Используйте этот шаблон, если требуется одна сводная строка для всей сущности.
Таблица SQL
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 | год | pages |
|---|---|---|---|
| 1 | Основы GraphQL | 2023 | 120 |
| 2 | Расширенные API | 2023 | 450 |
| 3 | Шаблоны данных | 2023 | 390 |
| 4 | Облачные API | 2024 | 140 |
| 5 | Внутренние компоненты среды выполнения | 2024 | 510 |
| 6 | Настройка запросов | 2024 | 250 |
Запрос GraphQL
{
books {
groupBy {
aggregations {
totalPages: sum(field: pages)
averagePages: avg(field: pages)
shortestBook: min(field: pages)
longestBook: max(field: pages)
bookCount: count(field: id)
}
}
}
}
Результирующий 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;
Результирующий результат
{
"data": {
"books": {
"groupBy": [
{
"aggregations": {
"totalPages": 1860,
"averagePages": 310,
"shortestBook": 120,
"longestBook": 510,
"bookCount": 6
}
}
]
}
}
}
| общее количество страниц | Среднее количество страниц | shortestBook | longestBook | bookCount |
|---|---|---|---|---|
| 1860 | 310 | 120 | 510 | 6 |
Группировать строки по одному полю
Используйте groupBy(fields: [...]), чтобы возвращать одну агрегированную строку для каждого значения поля. Имена полей — это значения перечисления GraphQL, а не строки.
Таблица SQL
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 | год | pages |
|---|---|---|---|
| 1 | Основы GraphQL | 2023 | 120 |
| 2 | Расширенные API | 2023 | 450 |
| 3 | Шаблоны данных | 2023 | 390 |
| 4 | Облачные API | 2024 | 140 |
| 5 | Внутренние компоненты среды выполнения | 2024 | 510 |
| 6 | Настройка запросов | 2024 | 250 |
Запрос GraphQL
{
books(orderBy: { year: ASC }) {
groupBy(fields: [year]) {
fields { year }
aggregations {
totalPages: sum(field: pages)
averagePages: avg(field: pages)
}
}
}
}
Результирующий 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;
Результирующий результат
{
"data": {
"books": {
"groupBy": [
{
"fields": {
"year": 2023
},
"aggregations": {
"totalPages": 960,
"averagePages": 320
}
},
{
"fields": {
"year": 2024
},
"aggregations": {
"totalPages": 900,
"averagePages": 300
}
}
]
}
}
}
| год | Всего страниц | среднее количество страниц |
|---|---|---|
| 2023 | 960 | 320 |
| 2024 | 900 | 300 |
Группировать строки из представления
Агрегирование также работает для сущностей, поддерживаемых представлением. Настройте ключевое поле для представления, чтобы построитель данных смог предоставить его как сущность.
представление SQL
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 | отдел | возраст |
|---|---|---|
| 1 | Инженерия | 29 |
| 2 | Инженерия | 41 |
| 3 | Sales | 34 |
| 4 | Sales | 52 |
| 5 | Support | 25 |
| 6 | Support | 38 |
| 7 | Инженерия | 45 |
Настройте представление, используя id в качестве ключевого поля:
dab add EmployeeAgeReport --source dbo.EmployeeAgeReport --source.type view --source.key-fields id --permissions "anonymous:read"
Запрос GraphQL
{
employeeAgeReports(orderBy: { department: ASC }) {
groupBy(fields: [department]) {
fields { department }
aggregations {
youngest: min(field: age)
oldest: max(field: age)
employeeCount: count(field: id)
}
}
}
}
Результирующий 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;
Результирующий результат
{
"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
}
}
]
}
}
}
| отдел | Младший | старейший | Количество сотрудников |
|---|---|---|---|
| Инженерия | 29 | 45 | 3 |
| Sales | 34 | 52 | 2 |
| Support | 25 | 38 | 2 |
Фильтрация строк перед агрегированием
Используйте filter в запросе коллекции, чтобы ограничить исходные строки до того, как Data API builder сгруппирует и агрегирует их.
представление SQL
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 | отдел | возраст |
|---|---|---|
| 1 | Инженерия | 29 |
| 2 | Инженерия | 41 |
| 3 | Sales | 34 |
| 4 | Sales | 52 |
| 5 | Support | 25 |
| 6 | Support | 38 |
| 7 | Инженерия | 45 |
Запрос GraphQL
{
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)
}
}
}
}
Результирующий 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;
Для этого запроса @param1 — это 30.
Результирующий результат
{
"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
}
}
]
}
}
}
| отдел | Младший | старейший | Количество сотрудников |
|---|---|---|---|
| Инженерия | 41 | 45 | 2 |
| Sales | 34 | 52 | 2 |
| Support | 38 | 38 | 1 |
Фильтрация групп с помощью having
Используйте having с агрегатной функцией, чтобы фильтровать группы после агрегации. Этот шаблон соответствует выражению SQL HAVING.
Таблица SQL
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 | ст-ти |
|---|---|---|
| 1 | Электроника | 5000.00 |
| 2 | Электроника | 10000,00 |
| 3 | Мебель | 4000.00 |
| 4 | Мебель | 8000.00 |
| 5 | Книги | 100.00 |
| 6 | Книги | 200.00 |
Запрос GraphQL
{
products(orderBy: { category: ASC }) {
groupBy(fields: [category]) {
fields { category }
aggregations {
totalValue: sum(field: price, having: { gt: 10000 })
averagePrice: avg(field: price)
}
}
}
}
Результирующий 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;
Для этого запроса @param1 — 10000.
Результирующий результат
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category": "Electronics"
},
"aggregations": {
"totalValue": 15000,
"averagePrice": 7500
}
},
{
"fields": {
"category": "Furniture"
},
"aggregations": {
"totalValue": 12000,
"averagePrice": 6000
}
}
]
}
}
}
| category | Общее значение | средняя цена |
|---|---|---|
| Электроника | 15000 | 7500 |
| Мебель | 12 000 | 6000 |
Подсчет уникальных значений
Используйте distinct: true вместе с count для подсчета уникальных значений в каждой группе.
Таблица SQL
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
{
orders(orderBy: { customer_id: ASC }) {
groupBy(fields: [customer_id]) {
fields { customer_id }
aggregations {
uniqueProducts: count(field: product_id, distinct: true)
totalOrders: count(field: id)
}
}
}
}
Результирующий 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;
Результирующий результат
{
"data": {
"orders": {
"groupBy": [
{
"fields": {
"customer_id": 101
},
"aggregations": {
"uniqueProducts": 5,
"totalOrders": 6
}
},
{
"fields": {
"customer_id": 102
},
"aggregations": {
"uniqueProducts": 3,
"totalOrders": 4
}
}
]
}
}
}
| customer_id | уникальные товары | Всего заказов |
|---|---|---|
| 101 | 5 | 6 |
| 102 | 3 | 4 |
Распространенные ошибки
- Выберите
groupByвнутри поля коллекции. Не передайтеgroupByв качестве аргумента коллекции. - Используйте
aggregations, а неaggregates. - Используйте
avg, а неaverage. - Используйте значения перечисления полей, например
fields: [year]. Не цитируйте имена полей. - Не выбирайте
itemsиgroupByв одном запросе коллекции. - При группировке по полям выберите только те же поля внутри
fieldsобъекта.