Workshop SQL 질의 변수
SQL query 변수는 모듈의 객체 집합과 다른 변수를 입력으로 받아 하나의 Ontology SQL SELECT 문으로 값을 계산합니다. 객체 집합과 인터페이스 집합을 테이블에, 다른 변수를 매개변수에 연결합니다.
RANK, ROW_NUMBER, LAG와 LEAD 같은 window 함수로 순위, 누적값과 기간 비교를 계산하거나, 여러 객체 집합을 JOIN하여 Struct Array로 반환하는 작업에 사용할 수 있습니다.
계산 방식 선택
| 방식 | 선택할 상황 |
|---|---|
| SQL query 변수 | 한 Workshop 앱에서 사용할 계산이 SQL로 표현하기 자연스러울 때 사용합니다. 모듈에 정의하므로 별도 게시와 버전 관리 대상이 생기지 않습니다. |
| SQL 함수 | 여러 앱과 Foundry 기능에서 같은 로직을 공유할 때 사용합니다. |
| TypeScript/Python 함수 기반 변수 | 해당 언어로 표현하는 편이 자연스럽거나 SELECT 문 밖의 기능이 필요할 때 사용합니다. |
| 변수 변환 | 일반적인 연산을 연결하는 간단한 앱 내부 계산에 사용합니다. |
| 객체 집합 변수 | 속성 필터나 연결 객체 탐색처럼 화면에서 구성하는 집합 연산에 사용합니다. |
SQL query 변수의 로직은 자신을 정의한 모듈에 속하며 다른 앱에서 재사용하는 함수가 아닙니다. 기본적으로 입력 변화에 따라 계산하고, 필요한 경우 재계산 방식을 이벤트 기반으로 바꿀 수 있습니다.
출력 자료형
| 변수 | SQL 결과 조건 |
|---|---|
| String, Numeric, Boolean, Date, Timestamp | 정확히 한 행, 한 열입니다. |
| 위 원시 자료형의 배열 | 정확히 한 열이며 10,000행 미만입니다. |
| Struct | 한 행의 각 열이 필드가 됩니다. 0행이면 변수값을 설정하지 않으며 두 행 이상은 오류입니다. |
| Struct Array | 10,000행 미만이며 한 행이 하나의 Struct가 됩니다. 0행이면 빈 배열입니다. |
Object set, GeoPoint와 GeoShape 변수는 SQL query 정의를 지원하지 않습니다. 배열 결과의 최대 행수는 9,999행입니다. 10,000행 이상이면 잘라서 사용하지 않고 LIMIT을 추가하도록 오류를 반환합니다. 이 기준은 SQL의 반환 행수에 적용됩니다.
변수와 테이블 구성
- Variables에서 지원 자료형의 변수를 만들거나 선택합니다.
- Variable definition type을 SQL query로 바꿉니다.
- Tables와 Parameters를 구성하고 SELECT 문을 작성합니다.
- Save and run으로 실행하여 변수값을 채웁니다.
Tables의 Add table에서 객체 집합 변수를 고르고 별칭을 붙입니다. 테이블은 @alias, 그 열은 @alias.column_name으로 참조합니다. 별칭은 문자 또는 밑줄로 시작하고 영숫자와 밑줄만 포함합니다.
각 테이블에는 열을 하나 이상 선택해야 합니다. COUNT(*)만 사용하더라도 테이블 바인딩의 열을 비워 두면 안 됩니다. 열 검색에서 필요한 속성을 추가합니다. 열이 없으면 다음 오류가 발생합니다.
Table binding '@alias' does not have any columns defined
가상의 orders 객체 집합을 @orders로 바인딩한 집계 예입니다.
SELECT COUNT(*) FROM @orders;
열 이름이 date이면 backtick으로 감쌉니다. 다음 예에서는 바인딩에 total과 date를 선택합니다.
SELECT AVG(@orders.total)
FROM @orders
WHERE @orders.`date` >= '2026-01-01';
인터페이스 집합도 테이블로 사용할 수 있습니다. 그 경우 사용할 열은 인터페이스의 속성이며 같은 인터페이스를 구현한 여러 객체 유형을 한 질의로 다룰 수 있습니다.
JOIN
여러 테이블을 바인딩하여 JOIN할 수 있습니다. 한쪽의 외래 키 속성과 다른 쪽의 기본 키를 연결하는 관계여야 합니다.
가상 orders의 customerId가 customers의 기본 키 id를 참조하는 예입니다. 두 열을 각각의 바인딩에 선택합니다.
SELECT COUNT(*)
FROM @orders
INNER JOIN @customers ON @orders.customerId = @customers.id;
ON 절에 쓰는 열도 SELECT 절과 마찬가지로 바인딩에 포함해야 합니다. 직접 기본 키/외래 키 관계가 아니라 별도 조인 테이블로 해결하는 다대다 관계는 이 기능에서 아직 지원하지 않습니다.
매개변수
Parameters의 Add parameter에서 변수를 선택하고 별칭을 붙입니다. 실행할 때 현재 값으로 대입하며 참조 구문은 테이블과 같은 @alias입니다.
가상의 지역 선택 String 변수를 @selectedRegion으로 연결하는 예입니다.
SELECT COUNT(*)
FROM @orders
WHERE @orders.region = @selectedRegion;
기본 자동 재계산에서는 연결한 매개변수가 바뀔 때 계산합니다. 이벤트 기반으로 설정했다면 명시적인 Recompute 이벤트가 필요합니다.
편집기와 미리보기
편집기는 바인딩한 테이블, 열과 매개변수를 자동 완성합니다. Save and run 또는 macOS의 Cmd+Enter, Windows의 Ctrl+Enter로 실행합니다. 문법과 함수는 Ontology SQL 및 SQL 참조를 따릅니다.
Query preview는 최대 50행의 원시 SQL 결과를 표시합니다. 변수 자료형이 받아들이지 못하는 결과 형태를 조정할 때도 반환 행과 열을 살펴볼 수 있습니다. 행 순서가 중요하면 ORDER BY를 명시합니다.
스칼라와 배열 결과
스칼라 변수는 한 행과 한 열을 요구합니다. 여러 행이나 열을 반환했다고 첫 값만 조용히 선택하지 않습니다.
배열 변수는 한 열의 모든 행을 사용합니다. 셀이 배열이면 그 원소를 하나의 결과 배열로 펼칩니다. 다음 두 문장은 각각 별도로 실행하는 배열 구성 예입니다.
한 배열 셀을 반환하는 경우:
SELECT array('a', 'b', 'c') AS value;
한 행에 이름 하나씩 반환하는 경우:
SELECT name FROM @employees ORDER BY name;
행의 값과 배열 원소가 null이면 결과에서 제외합니다. 결과 행이 없으면 빈 배열을 설정합니다. 결과가 10,000행 이상이면 오류를 내므로 필요한 범위와 LIMIT을 쿼리에 지정합니다.
Struct 결과와 필드
Struct의 각 필드는 결과 열에서 이름과 자료형을 가져옵니다. 한 행이 하나의 Struct이며 중첩 Struct는 지원하지 않습니다. Struct Array는 같은 규칙으로 여러 행을 담습니다.
성공적으로 다시 실행하면 열 추가, 삭제, 이름 변경과 자료형 변경을 필드에 반영합니다. 위젯이 사용하던 열을 더 이상 반환하지 않으면 그 필드 연결이 깨지므로 관련 위젯도 확인합니다. 값이 null인 열은 필드는 존재하되 해당 필드값이 없는 Struct를 만듭니다.
SELECT 목록의 조건
- 모든 열에 사용할 수 있는 일반 식별자 이름이 있어야 합니다. COUNT(*) 같은 계산 열에는
AS order_count처럼 별칭을 붙입니다. - 열 이름은 고유해야 합니다. 같은 이름의 두 열은 AS로 구분합니다.
- Struct, map과 binary 열은 필드로 직접 사용할 수 없습니다.
- 배열 열은 지원합니다. 예를 들어
ARRAY<STRING>열은 문자열 목록 필드가 됩니다. Struct의 배열은 필드로 지원하지 않습니다.
가상의 @t가 name과 addr 속성을 갖고 addr 안에 city가 있다고 가정합니다.
| 별도로 실행할 문장 | Struct 결과의 조건 |
|---|---|
SELECT name FROM @t | 한 행이면 name 필드를 가진 Struct입니다. |
SELECT @t.addr.* FROM @t | addr의 각 필드를 펼칩니다. city가 필드가 됩니다. |
SELECT @t.addr FROM @t | Struct 열 자체를 필드로 넣으므로 오류입니다. |
SELECT name, name FROM @t | 필드 이름이 중복되어 오류입니다. |
SELECT COUNT(*) FROM @t | 계산 열에 사용할 별칭이 필요하므로 Struct 구성에서는 오류입니다. |
기존 Struct 속성은 .*로 펼쳐 필드를 일일이 나열하지 않을 수 있습니다. 테이블 별칭을 포함한 참조가 필요합니다.
SELECT @t.structField.*
FROM @t;
structField에 street, city와 postalCode가 있으면 그 세 열이 필드가 됩니다. 다른 열과 함께 선택할 수도 있습니다.
SELECT @t.name, @t.addressStruct.*
FROM @t;
펼친 필드 이름과 다른 열의 이름이 겹치지 않아야 합니다.
Struct 질의 저장
Struct 계열은 질의와 파생 필드를 함께 저장합니다. Save and run이 먼저 질의를 실행하고 반환 열이 Struct를 구성할 수 있을 때만 둘을 저장합니다. 실행이나 열 형식이 실패하면 저장하지 않고 편집기의 초안을 유지하며 이전에 저장한 질의와 필드는 계속 유효합니다. 오류는 미리보기 위와 편집기 안에 표시합니다.
게시한 앱이 실행될 때도 저장한 필드를 검사합니다. 기반 데이터 변화로 기대한 열 형태가 맞지 않으면 다른 모양으로 조용히 바꾸지 않고 관련 열을 지목하는 오류를 반환합니다.
AIP로 질의 작성
구할 값을 자연어로 입력하면 AIP가 구성한 테이블, 매개변수와 출력 자료형에 맞는 Ontology SQL을 작성합니다. 사용할 수 있는 별칭과 열의 범위로 제한합니다.
생성한 질의는 편집기에 들어간 뒤 자동 실행됩니다. 결과를 확인하고 필요하면 질의를 수정합니다. 단순히 실행하지 않은 초안만 생성하는 동작으로 취급하지 않습니다.
부서별 최고 급여자
가상의 @employees에 name, salary와 department를 선택하고 부서 String 변수를 @department로 연결합니다. 다음 RANK 질의는 선택 부서의 공동 최고 급여자를 모두 반환할 수 있으므로 String Array 변수에 연결합니다.
SELECT name
FROM (
SELECT name AS name,
RANK() OVER (ORDER BY salary DESC) AS salary_rank
FROM @employees
WHERE department = @department
)
WHERE salary_rank = 1
ORDER BY name;
동률이면 여러 행을 반환하므로 한 행만 받는 String 변수에는 맞지 않습니다. 부서에 객체가 없으면 배열은 비어 있습니다. 단일 대상을 고르는 업무라면 동률 처리 기준을 먼저 정해야 합니다.
부서 요약 Struct
같은 입력에서 여러 관련 수치를 한 번에 계산합니다. 각 열에 이름을 붙여 하나의 Struct로 받습니다.
SELECT COUNT(*) AS headcount,
AVG(salary) AS average_salary,
MAX(salary) AS top_salary
FROM @employees
WHERE department = @department;
상위 목록 Struct Array
급여가 높은 순서로 최대 열 행을 반환하여 반복 화면의 입력으로 사용할 수 있습니다. 다음 질의는 같은 급여 사이의 순서를 정하지 않습니다. 그 순서도 중요하면 업무에 맞는 추가 정렬 기준을 지정합니다.
SELECT name,
salary
FROM @employees
WHERE department = @department
ORDER BY salary DESC
LIMIT 10;
Struct값의 입력과 필드 추출은 Struct 변수, 이 결과를 레이아웃 상태에 연결하는 방식은 변수 기반 레이아웃에 설명합니다.