Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Построитель 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 поддерживает следующие агрегатные функции:
| Функция | Применимо к | Описание |
|---|---|---|
sum |
Числовые поля только | Общее количество всех значений |
average |
Числовые поля только | Среднее значение всех значений |
min |
Числовые поля только | Минимальное значение |
max |
Числовые поля только | Максимальное значение |
count |
Любое поле | Количество непустых значений |
Constraints
-
sum, ,averageminиmaxтолько работают с числовыми типами данных (int, decimal, float и т. д.). -
countработает с любым типом данных, включая строки и даты. - Если в таблице нет числовых столбцов, DAB не создает узлы агрегирования для этой сущности. Вы по-прежнему можете использовать
countв нечисловых полях.
Необязательные модификаторы
| Модификатор | Purpose | Пример |
|---|---|---|
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
| Оператор | Эквивалент SQL | Пример |
|---|---|---|
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столбцов для повышения производительности запросов.
Troubleshooting
Ошибка: поле не поддерживает агрегирование
Причина: использование sum, averageminили max в нечисловом поле.
Решение.
- Используйте интроспекцию схемы для проверки типов полей.
- Используется
countдля нечисловых полей. - Проверьте сопоставления полей при использовании пользовательских наименований полей.
Ошибка: узлы агрегирования не найдены
Причина. Сущность не имеет числовых столбцов.
Решение.
- Убедитесь, что схема таблицы имеет по крайней мере один числовой столбец.
- При необходимости используйте агрегаты
countдля нечисловых полей.
Медленные запросы на агрегацию
Причина: большие таблицы без правильных индексов.
Решение.
- Создайте индексы для
groupByстолбцов. - Используйте
filterдля ограничения строк перед агрегированием. - Используйте
having, чтобы уменьшить число возвращаемых групп.