Data API Builder는 SQL Server 제품군 및 Azure Synapse Analytics 전용 SQL 풀 엔터티에 대한 GraphQL 집계를 지원합니다. 컬렉션 쿼리의 groupBy 필드를 사용하여 , sum, avgmin및 max 값을 계산count합니다.
이 문서의 예제에서는 읽기 권한이 있는 SQL Server 및 GraphQL 엔터티를 사용합니다. 데이터 API 작성기에서는 각 시나리오에 표시된 문처럼 SQL을 생성합니다. 매개 변수 값은 런타임에 쿼리 매개 변수로 표시됩니다.
sum, avg, min및 max 함수는 숫자 필드에 적용됩니다. 함수는 count 모든 필드에서 작동합니다.
Important
집계는 Azure Cosmos DB for NoSQL, PostgreSQL 또는 MySQL에서는 사용할 수 없습니다.
집계는 기본적으로 사용하도록 설정됩니다. 끄려면 구성 파일에서 runtime.graphql 아래의 enable-aggregation을 false로 설정하세요. 집계 쿼리는 기본적으로 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
데이터 API 작성기에서 집계 값을 계산한 후 그룹을 필터링합니다.
aggregations { <alias>: <function>(field: <field>, having: { <operator>: <value> }) }
distinct
와 함께 count사용할 때 고유 값의 개수를 계산합니다.
aggregations { <alias>: count(field: <field>, distinct: true) }
데이터 API 작성기는 그룹 행 형식, 그룹화된 필드 형식, 집계 선택 유형, 필드 열거형 및 having 입력 형식을 포함하여 이러한 멤버 뒤에 엔터티별 GraphQL 형식을 생성합니다. 쿼리에서 생성된 형식의 이름을 지정할 필요가 없습니다.
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
}
}
]
}
}
}
| 연도 | totalPages | 평균 페이지 |
|---|---|---|
| 2023 | 960 | 320 |
| 2024 | 900 | 300 |
보기에서 행 그룹화
집계는 뷰 기반 엔터티에도 또한 지원됩니다. 데이터 API 작성기에서 뷰를 엔터티로 노출할 수 있도록 보기에 대한 키 필드를 구성합니다.
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 | 공학 | 이십구 |
| 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
}
}
]
}
}
}
| 부서 | 가장 어린 | 가장 오래된 | 직원 수 |
|---|---|---|---|
| 공학 | 이십구 | 45 | 3 |
| Sales | 34 | 52 | 2 |
| Support | 25 | 38 | 2 |
집계 전에 행 필터링하기
컬렉션 쿼리에 filter를 사용하여 Data API 빌더가 그룹화하고 집계하기 전에 원본 행을 제한하세요.
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 | 공학 | 이십구 |
| 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;
이 쿼리의 경우 다음과 같습니다 @param130.
결과 출력
{
"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 | 카테고리 | 가격 |
|---|---|---|
| 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;
이 쿼리의 경우 다음과 같습니다 @param110000.
결과 출력
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category": "Electronics"
},
"aggregations": {
"totalValue": 15000,
"averagePrice": 7500
}
},
{
"fields": {
"category": "Furniture"
},
"aggregations": {
"totalValue": 12000,
"averagePrice": 6000
}
}
]
}
}
}
| 카테고리 | 총값 | 평균 가격 |
|---|---|---|
| 전자 | 15000 | 7,500 |
| 가구 | 12000 | 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 | uniqueProducts | 총 주문 수 |
|---|---|---|
| 101 | 5 | 6 |
| 102 | 3 | 4 |
일반적인 실수
- 컬렉션 필드 내에서
groupBy을 선택합니다. 컬렉션 인수로 전달groupBy하지 마세요. -
aggregations이 아니라aggregates을 사용합니다. -
avg이 아니라average을 사용합니다. - 필드 열거형 값(예:
fields: [year].)을 사용합니다. 필드 이름을 인용하지 마세요. - 동일한 컬렉션 쿼리에서 선택
itemsgroupBy하지 마세요. - 필드별로 그룹화할 때 개체 내에서
fields동일한 필드만 선택합니다.