Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Построитель API данных (DAB) поддерживает агрегирование и группирование в GraphQL для баз данных семейства SQL и Azure Synapse Analytics (выделенный пул SQL). Агрегаты позволяют суммировать числовые поля и результаты группы без написания пользовательского кода API. Агрегирование и groupBy недоступно для Azure Cosmos DB для NoSQL, PostgreSQL или MySQL.
Предпосылки
- Поддерживаемая база данных:
- SQL Server 2016 или более поздней версии.
- База данных SQL Azure
- Управляемый экземпляр SQL Azure
- Microsoft Fabric SQL
- Azure Synapse Analytics (только выделенный пул SQL)
- CLI инструмента построения API данных. Установка интерфейса командной строки
- Файл конфигурации DAB с сущностью, доступной через GraphQL.
- Клиент GraphQL (например, Banana Cake Pop или GraphQL Playground) для выполнения запросов.
Поддерживаемые базы данных
| База данных | Поддержка агрегирования |
|---|---|
| SQL Server / Azure SQL / Microsoft Fabric SQL | ✅ Да |
| Azure Synapse (выделенный пул SQL) | ✅ Да |
| Azure Synapse (бессерверный пул SQL) | ❌ Нет |
| PostgreSQL | ❌ Нет |
| MySQL | ❌ Нет |
| Azure Cosmos DB для NoSQL | ❌ Нет |
Агрегатные функции
DAB поддерживает следующие агрегатные функции:
| Функция | Применимо к | Description |
|---|---|---|
sum |
Числовые поля только | Общее количество всех значений |
average |
Числовые поля только | Среднее значение всех значений |
min |
Числовые поля только | Минимальное значение |
max |
Числовые поля только | Максимальное значение |
count |
Любое поле | Количество непустых значений |
Constraints
-
sum, ,averageminиmaxтолько работают с числовыми типами данных (int, decimal, float и т. д.). -
countработает с любым типом данных, включая строки и даты. - Если в таблице нет числовых столбцов, DAB не создает узлы агрегирования для этой сущности. Вы по-прежнему можете использовать
countв нечисловых полях.
Необязательные модификаторы
| Модификатор | Цель | Example |
|---|---|---|
distinct: true |
Подсчитывать только уникальные значения | Подсчет отдельных клиентов |
having: { ... } |
Фильтрация групп после агрегирования | Отображение групп с суммой > 1000 |
Запуск среды выполнения DAB
Запустите DAB с файлом конфигурации, чтобы конечная точка GraphQL была доступна.
dab start
Агрегированные результаты запроса
В этом разделе приведен полный пример схемы таблицы, запроса GraphQL, созданного SQL и ответа JSON.
Схема таблицы
CREATE TABLE books (
id INT PRIMARY KEY,
title NVARCHAR(200),
year INT,
pages INT
);
Запрос GraphQL
Используйте GraphQL для группирования строк и возврата статистических значений для числовых полей.
{
books(
groupBy: { fields: ["year"] }
) {
items {
year
}
aggregates {
pages {
sum
average
min
max
}
}
}
}
-
groupBy.fieldsгруппирует строки по указанным столбцам. -
aggregatesпредоставляет агрегатные функции для числовых полей (например,pages). - Схема GraphQL предоставляет статистические данные только для полей, поддерживающих их; используйте интроспекцию схемы в клиенте для подтверждения доступных статистических полей и функций.
Созданный SQL
DAB преобразует запрос GraphQL в 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
{
"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 }
]
}
}
}
}
Массивы items и aggregates выровнены по индексам — первый элемент в aggregates.pages соответствует первой группе в items.
Агрегирование без группировки
Вычисляйте агрегаты во всех строках, если вы опускаете groupBy.
Запрос GraphQL
{
books {
aggregates {
pages {
sum
average
min
max
count
}
id {
count
}
}
}
}
Созданный 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
{
"data": {
"books": {
"aggregates": {
"pages": {
"sum": 15420,
"average": 308,
"min": 120,
"max": 850,
"count": 50
},
"id": {
"count": 50
}
}
}
}
}
Без groupBy этого ответ возвращает один объект (а не массив), так как все строки объединяются в один результат.
Группировать по одному или нескольким полям
Группировать строки по одному или нескольким столбцам и возвращать суммарные значения для каждой группы.
Схема таблицы
CREATE TABLE sales (
id INT PRIMARY KEY,
year INT,
category NVARCHAR(50),
revenue DECIMAL(10,2),
quantity INT
);
Запрос GraphQL
{
sales(
groupBy: { fields: ["year", "category"] }
) {
items {
year
category
}
aggregates {
revenue {
sum
average
}
quantity {
sum
}
}
}
}
Созданный 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
{
"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 }
]
}
}
}
}
Ответ возвращает массивы для items и агрегатов в том же порядке, чтобы можно было выровнять группы с агрегированными значениями.
Необходимость фильтрации агрегированных результатов
Используется having для фильтрации групп после агрегирования. Это эквивалентно предложению SQL HAVING .
Схема таблицы
CREATE TABLE products (
id INT PRIMARY KEY,
category NVARCHAR(50),
price DECIMAL(10,2)
);
Запрос GraphQL
{
products(
groupBy: { fields: ["category"] }
) {
items { category }
aggregates {
price {
sum(having: { gt: 10000 })
average
}
}
}
}
Созданный 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
Возвращаются только категории, в которых сумма превышает 10000:
{
"data": {
"products": {
"items": [
{ "category": "Electronics" },
{ "category": "Furniture" }
],
"aggregates": {
"price": [
{ "sum": 15000.00, "average": 300.00 },
{ "sum": 12000.00, "average": 400.00 }
]
}
}
}
}
Операторы HAVING
| Operator | Эквивалент SQL | 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 } |
Замечание
Каждый having фильтр применяется независимо к своей агрегатной функции. Невозможно создать межрегистрационные условия, такие как "сумма > 1000 OR count < 10" в одном запросе GraphQL.
DISTINCT в агрегациях
Подсчет уникальных значений с distinct: true.
Схема таблицы
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
product_id INT
);
Запрос GraphQL
{
orders(
groupBy: { fields: ["customer_id"] }
) {
items { customer_id }
aggregates {
product_id {
count(distinct: true)
count
}
}
}
}
Созданный 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
{
"data": {
"orders": {
"items": [
{ "customer_id": 101 },
{ "customer_id": 102 }
],
"aggregates": {
"product_id": [
{ "count": 5 },
{ "count": 3 }
]
}
}
}
}
Первый count (с distinct: true) возвращает уникальные продукты для каждого клиента.
count Второй возвращает общее количество заказов.
Замечание
При запросе нескольких агрегатов в одном поле DAB возвращает их в запрошенном порядке. Используйте псевдонимы (например, uniqueProducts: count(distinct: true)для самостоятельного документирования ответов).
Объединение фильтров с агрегированием
Примените filter к строкам перед группировкой и having к группам после агрегирования. Понимание порядка операций имеет решающее значение:
-
Фильтр (SQL
WHERE) удаляет строки перед группировкой - Group by собирает оставшиеся строки в группы
- Агрегат вычисляет сумму/среднее/минимум/максимум/количество на группу
- Удаление групп, которые не соответствуют условию
Запрос GraphQL
{
sales(
filter: { year: { gte: 2023 } }
groupBy: { fields: ["region"] }
) {
items { region }
aggregates {
revenue { sum average }
}
}
}
Созданный 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
Подсказка
Используется filter для исключения строк перед агрегированием. Используется having для фильтрации групп после агрегирования.
Использование псевдонимов с агрегациями
Создание значимых имен полей с помощью псевдонимов GraphQL.
{
products(
groupBy: { fields: ["category"] }
) {
items { category }
aggregates {
price {
totalRevenue: sum
avgPrice: average
cheapest: min
mostExpensive: max
productCount: count
}
}
}
}
Интроспектация схемы
Используйте интроспекцию, чтобы узнать, какие агрегаты доступны для сущности.
{
__type(name: "BooksAggregates") {
fields {
name
type { name }
}
}
}
Числовые поля предоставляют sum, average, min, max и count. Нечисловые поля показывают count.
Советы и ограничения
- Агрегирование и
groupByприменяются только к SQL Server, Azure SQL, Microsoft Fabric SQL и выделенному пулу Azure Synapse Dedicated SQL. - Агрегатные функции работают с числовыми полями;
countработает с любым полем. Таблицы без числовых столбцов заявляют толькоcount. - Группирование применяется к полям в одной сущности (без группы между сущностами).
- Крупные агрегаты могут быть дорогостоящими. Индексируйте столбцы 'groupBy' и фильтруйте строки перед группировкой, если это возможно.
- Создавайте индексы для часто используемых
groupByстолбцов для повышения производительности запросов.
Устранение неполадок
Ошибка: поле не поддерживает агрегирование
Причина: использование sum, averageminили max в нечисловом поле.
Решение.
- Используйте интроспекцию схемы для проверки типов полей.
- Используется
countдля нечисловых полей. - Проверьте сопоставления полей при использовании пользовательских наименований полей.
Ошибка: узлы агрегирования не найдены
Причина. Сущность не имеет числовых столбцов.
Решение.
- Убедитесь, что схема таблицы имеет по крайней мере один числовой столбец.
- При необходимости используйте агрегаты
countдля нечисловых полей.
Медленные запросы на агрегацию
Причина: большие таблицы без правильных индексов.
Решение.
- Создайте индексы для
groupByстолбцов. - Используйте
filterдля ограничения строк перед агрегированием. - Используйте
having, чтобы уменьшить число возвращаемых групп.