데이타베이스/SqlServer

고급 SQL 쿼리: 윈도우 함수, 공통 테이블 표현식, 동적 SQL, 그리고 XML 및 JSON 처리

shimdh 2025. 1. 24. 17:42
728x90

1. 윈도우 함수

개요

윈도우 함수는 데이터의 특정 부분(윈도우)을 기준으로 계산을 수행하며, 집계 함수와 달리 원본 데이터의 각 행에 결과를 유지합니다. 이를 통해 순위 계산, 누적 합계, 이동 평균 등 다양한 분석 작업을 간단히 수행할 수 있습니다. 데이터 분석 전문가에게 필수적인 기술로 자리 잡았으며, SQL을 사용하는 모든 데이터베이스 관리 시스템에서 지원됩니다.

윈도우 함수는 특히 금융, 마케팅, 공급망 분석에서 많이 사용됩니다. 예를 들어, 누적 매출 계산, 판매 순위 분석, 시간에 따른 평균 매출 변화 등을 수행하는 데 적합합니다.

기본 구조

함수명(열) OVER (PARTITION BY 열 ORDER BY 열)
  • 함수명: SUM, AVG, ROW_NUMBER 등 다양한 함수 사용 가능
  • PARTITION BY: 데이터를 그룹화하여 각 그룹 내에서 계산
  • ORDER BY: 각 파티션 내에서 행의 순서 정의

윈도우 함수는 집계 함수와 달리 데이터를 그룹화하면서도 각 행에 세부 결과를 유지하기 때문에, 기존 데이터를 잃지 않고 추가적인 분석 정보를 얻을 수 있습니다.

윈도우 함수의 주요 활용 사례

누적 합계 계산

누적 합계는 데이터를 시간 순서대로 누적하여 특정 시점까지의 합계를 계산하는 데 유용합니다.

SELECT
    판매일,
    금액,
    SUM(금액) OVER (ORDER BY 판매일) AS 누적_합계
FROM
    판매테이블;

위 쿼리는 판매 데이터를 날짜별로 누적 합계를 계산하며, 시간 흐름에 따른 매출 성과를 추적하는 데 효과적입니다. 이는 월별, 분기별 매출 성과를 분석하거나 특정 캠페인 효과를 측정하는 데도 활용됩니다.

순위 매기기

데이터 집합에서 특정 열을 기준으로 순위를 부여하는 작업은 흔히 필요합니다.

SELECT
    학생ID,
    성적,
    RANK() OVER (ORDER BY 성적 DESC) AS 순위
FROM
    학생성적테이블;

위 예제는 학생들의 성적을 기준으로 높은 점수부터 순위를 매깁니다. 순위 함수는 RANK, DENSE_RANK, ROW_NUMBER 등으로 다양하게 활용 가능합니다. RANK()는 동점자에게 동일한 순위를 부여하지만, ROW_NUMBER()는 모든 행에 고유한 순위를 매깁니다.

이동 평균 계산

이동 평균은 특정 기간 동안의 평균을 계산하여 트렌드를 분석하는 데 사용됩니다.

SELECT
    판매일,
    금액,
    AVG(금액) OVER (ORDER BY 판매일 ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) AS 이동_평균_5일치
FROM
    판매테이블;

최근 5일 동안의 평균 매출을 계산함으로써 트렌드를 보다 정확히 파악할 수 있습니다. 이를 통해 비즈니스 의사 결정 시 유용한 통찰을 제공합니다. 예를 들어, 매출 감소 추세를 조기에 발견하거나 마케팅 캠페인의 성공 여부를 판단할 수 있습니다.


2. 공통 테이블 표현식 (CTE)

개요

공통 테이블 표현식(CTE)은 복잡한 쿼리를 간결하고 읽기 쉽게 작성할 수 있도록 도와줍니다. 또한, 계층적 데이터 처리와 재귀 쿼리에 특히 유용하여, 서브쿼리의 중복 사용을 줄이고 데이터 조작을 효율화할 수 있습니다. CTE는 SQL Server, PostgreSQL, MySQL 등 주요 데이터베이스 시스템에서 지원됩니다.

CTE는 단순히 데이터를 필터링하거나 요약하는 데 그치지 않고, 여러 단계를 거쳐 데이터의 흐름을 명확히 보여줄 수 있는 장점이 있습니다. 따라서 데이터 분석 보고서 작성이나 자동화된 데이터 파이프라인 구축에 적합합니다.

기본 구조

WITH CTE_Name AS (
    -- 서브쿼리 작성
)
SELECT * FROM CTE_Name;

이 구조를 활용하면 반복적으로 사용되는 복잡한 로직을 간결하게 정의하고 재사용할 수 있습니다.

주요 사용 사례

계층적 데이터 처리

계층적 데이터, 예를 들어 회사의 직원-관리자 관계를 처리하는 데 유용합니다.

WITH RecursiveHierarchy AS (
    SELECT EmployeeID, Name, ManagerID
    FROM Employees
    WHERE ManagerID IS NULL  -- 최상위 관리자

    UNION ALL

    SELECT e.EmployeeID, e.Name, e.ManagerID
    FROM Employees e
    INNER JOIN RecursiveHierarchy rh ON e.ManagerID = rh.EmployeeID
)
SELECT * FROM RecursiveHierarchy;

위 예제는 최상위 관리자부터 하위 직원까지의 관계를 계층적으로 정리하여 보여줍니다. 대규모 조직 데이터를 효율적으로 관리할 수 있습니다. 특히, 조직도를 생성하거나 보고 체계를 분석하는 데 유용합니다.

집계 함수와 함께 사용

CTE는 집계 함수와 함께 사용하여 특정 그룹의 데이터를 손쉽게 분석할 수 있습니다.

WITH DepartmentSalaries AS (
    SELECT DepartmentId, AVG(Salary) AS AvgSalary
    FROM Employees
    GROUP BY DepartmentId
)
SELECT d.DepartmentId, ds.AvgSalary
FROM Departments d
JOIN DepartmentSalaries ds ON d.DepartmentId = ds.DepartmentId;

부서별 평균 연봉을 계산하고 이를 다양한 차원에서 분석하는 데 활용할 수 있습니다. 이는 인력 자원의 효율성을 평가하거나 예산 계획에 중요한 데이터를 제공합니다.

복잡한 데이터 조작 간소화

CTE는 복잡한 데이터 변환 작업을 여러 단계로 나누어 처리함으로써, 읽기 쉽고 유지보수가 용이한 쿼리를 작성할 수 있습니다. 예를 들어, 중첩된 서브쿼리를 단일 CTE로 대체하면, 쿼리 성능을 개선하고 디버깅을 용이하게 만들 수 있습니다.


3. 동적 SQL

개요

동적 SQL은 실행 시점에 SQL 문을 생성하고 실행하여, 조건에 따라 쿼리를 유연하게 변경할 수 있습니다. 이를 통해 다양한 사용자 입력 조건이나 필터링 요구사항을 효과적으로 처리할 수 있습니다.

동적 SQL은 특히 데이터 탐색이 자주 이루어지는 환경, 사용자 맞춤형 대시보드, 또는 조건에 따라 쿼리 구조가 자주 변경되는 애플리케이션에서 유용합니다.

구현 방법

EXEC 사용

EXEC 명령어는 동적 SQL을 간단히 실행하는 방법입니다.

DECLARE @sql NVARCHAR(MAX);
SET @sql = 'SELECT * FROM Employees WHERE DepartmentID = ' + CAST(@DepartmentID AS NVARCHAR(10));
EXEC(@sql);

sp_executesql 사용

sp_executesql은 매개변수를 안전하게 처리할 수 있는 동적 SQL 실행 방법입니다.

DECLARE @sql NVARCHAR(MAX);
DECLARE @paramDefinition NVARCHAR(100);

SET @sql = N'SELECT * FROM Employees WHERE DepartmentID = @DeptID';
SET @paramDefinition = N'@DeptID INT';

EXEC sp_executesql @sql, @paramDefinition, @DeptID;

이 방법은 SQL 인젝션 방지에 효과적이며, 보안과 성능 면에서 권장됩니다.

활용 예제: 필터링 및 검색

동적 SQL은 복잡한 조건을 동적으로 처리할 수 있습니다.

DECLARE @CategoryId INT;
DECLARE @PriceMin DECIMAL(10,2);
DECLARE @PriceMax DECIMAL(10,2);

SET @CategoryId = 1;
SET @PriceMin = 1000;
SET @PriceMax = 5000;

DECLARE @sql NVARCHAR(MAX) = 'SELECT * FROM Products WHERE CategoryId = ' + CAST(@CategoryId AS NVARCHAR) +
                              ' AND Price BETWEEN ' + CAST(@PriceMin AS NVARCHAR) +
                              ' AND ' + CAST(@PriceMax AS NVARCHAR);

EXEC (@sql);

위 예제는 특정 카테고리와 가격 범위에 해당하는 제품 목록을 검색합니다. 이를 통해 쇼핑몰 같은 시스템에서 사용자 맞춤형 데이터를 제공합니다.

동적 SQL은 잘 활용하면 매우 강력하지만, 보안 문제를 고려해야 합니다. 매개변수화를 통해 SQL 인젝션 공격을 방지하는 것이 필수적입니다.


4. XML 및 JSON 처리

XML 처리

XML 데이터는 복잡한 데이터 구조를 처리하거나 다른 시스템과의 통합에서 중요합니다. 특히 대규모 엔터프라이즈 환경에서는 XML을 통해 데이터를 교환하는 사례가 많습니다.

XML 데이터 생성 및 쿼리

DECLARE @xmlData xml;
SET @xmlData = '<학생들><학생><이름>홍길동</이름><나이>20</나이></학생></학생들>';
SELECT @xmlData.query('/학생들/학생/이름') AS 학생이름;

이 코드는 XML 데이터에서 특정 정보를 추출합니다.

테이블 데이터를 XML로 변환

SELECT 이름, 나이
FROM 학생
FOR XML PATH('학생'), ROOT('학생들');

이 쿼리는 학생 데이터를 XML 형식으로 변환하여 다른 시스템과의 연동에 유용합니다. 예를 들어, ERP 시스템과의 데이터 교환에 활용할 수 있습니다.

JSON 처리

JSON 데이터는 현대 웹 애플리케이션에서 흔히 사용됩니다. 특히 RESTful API와 같은 현대적인 데이터 전송 방법에서 표준 포맷으로 자리 잡았습니다.

JSON 생성 및 파싱

DECLARE @json NVARCHAR(MAX) = N'[{"이름":"홍길동","나이":20},{"이름":"김철수","나이":22}]';
SELECT *
FROM OPENJSON(@json)
WITH (
    이름 NVARCHAR(50),
    나이 INT
);

테이블 데이터를 JSON으로 변환

SELECT 이름, 나이
FROM 학생
FOR JSON AUTO;

이 쿼리는 데이터를 JSON 형식으로 반환하며, RESTful API 개발에서 유용합니다. 프론트엔드 애플리케이션과 통신하거나 모바일 앱에 데이터를 제공하는 데 적합합니다.


결론

SQL의 고급 기능인 윈도우 함수, 공통 테이블 표현식, 동적 SQL, 그리고 XML 및 JSON 처리는 복잡한 데이터 분석과 통합 작업을 효율적으로 수행하는 데 필수적입니다. 이들 기술을 활용하면 대규모 데이터 작업을 더 빠르고 정확하게 처리할 수 있으며, 다양한 비즈니스 요구사항에 신속히 대응할 수 있습니다. 실무에서 이러한 기술을 적용하고 익숙해지면 데이터 처리 능력이 크게 향상될 것입니다.

데이터 분석, 관리, 통합의 모든 단계에서 이들 고급 SQL 기능을 활용해 보세요. 이를 통해 조직의 데이터 활용도를 극대화하고, 더 나은 비즈니스 결정을 내릴 수 있는 강력한 도구를 얻게 될 것입니다.

728x90