분산된 플레이어 GGR/게임 지표를 통합하고 QA/운영에서 재사용 가능한 SQL 조회 구조를 설계

| 역할 | 테이블 (가칭) | 조인방식 | 설명 |
| 기본 플레이어 정보 | alias1 | 기준 테이블 | 플레이어 ID, 이메일, 닉네임, 국가, 사이트, 소속 유형 등 |
| 플레이어 소속/에이전트 | alias2 | LEFT JOIN | 각 플레이어의 Agent 코드 조회 |
| 게임별 통계 | alias3 | LEFT JOIN | Poker GGR, Casino GGR, Reward, T/O 등 핵심 수익 지표 |
| 최신 개인 정보 | alias4 | OUTER APPLY | 조건에 따라 최신 Tag / Code(가칭) 값 추출 |
| 플레이어 태그 | alias5 | 서브쿼리 | COUNT, 문자열 집계(STUFF + FOR XML PATH)로 태그 목록 생성 |
OUTER APPLY 사용 포인트
1. 언제쓰는 게 좋을지: 기준 테이블 행마다 최신/특정 조건 데이터를 가져올 때
2. 유용한 점: LEFT JOIN으로는 구현하기 어려운 조건/정렬 적용 가능
기준 행별 다른 최신 데이터를 유연하게 가져올 수 있음
3. 주의할 점: 데이터 양 많으면 성능 영향 가능 → 인덱스 최적화 필요
가독성을 위해 주석과 함께 사용
SELECT
-- 1. 기본 정보
p.Id AS [Player ID],
ISNULL(p.Email, '') AS [Email Address],
ISNULL(p.MobileNumber, '') AS [Mobile Number],
p.Username AS [Username],
ISNULL(p.Nickname, '') AS [Nickname],
CASE
WHEN p.AssociationType = 0 THEN 'Brand'
WHEN p.AssociationType = 1 THEN 'Affiliate'
WHEN p.AssociationType = 2 THEN 'Agent'
ELSE CAST(p.AssociationType AS VARCHAR)
END AS [AssociationType],
-- 2. PlayerAgent 테이블의 Code 값
ISNULL(pa.Code, '') AS [Agent],
-- SiteId == SiteName
CASE p.Site
WHEN 0 THEN 'None' WHEN 1 THEN 'GGPCOM' WHEN 2 THEN 'GGPEU' WHEN 3 THEN 'GGPPL'
WHEN 4 THEN 'GGPDE' WHEN 5 THEN 'GGPNL' WHEN 6 THEN 'GGPRO' WHEN 7 THEN 'GGPJP'
WHEN 8 THEN 'GGPBE' WHEN 9 THEN 'GGPCZ' WHEN 10 THEN 'GGPUK' WHEN 11 THEN 'GGPOK'
WHEN 12 THEN 'GGPUKE' WHEN 13 THEN 'SevenXL' WHEN 14 THEN 'Natural8' WHEN 15 THEN 'DavaoPoker'
WHEN 16 THEN 'GGPRU' WHEN 17 THEN 'GGPHU' WHEN 18 THEN 'GGPNG' WHEN 19 THEN 'GGPCW'
WHEN 20 THEN 'TWOACE' WHEN 22 THEN 'GGPBR' WHEN 23 THEN 'GGPUA' WHEN 24 THEN 'EVPUKE'
WHEN 25 THEN 'GGPFI' WHEN 27 THEN 'WSOPON' WHEN 28 THEN 'N8IN' WHEN 29 THEN 'GGPPH'
WHEN 30 THEN 'GGPDK' WHEN 31 THEN 'OCNP' WHEN 32 THEN 'PokerArabia' WHEN 33 THEN 'GGVCOM'
WHEN 34 THEN 'GGPBG' WHEN 35 THEN 'GGPBA' WHEN 36 THEN 'GGPSE' WHEN 37 THEN 'GGVSYS'
WHEN 38 THEN 'GGVON'
ELSE CAST(p.Site AS VARCHAR)
END AS [Site],
ISNULL(p.Country, '') AS [Country],
ISNULL(CAST(p.AffiliateMemberId AS VARCHAR), '') AS [Affiliate Id],
-- 3. IsOfflineCode 조건 배분
ISNULL(ppi_latest.[B tag], '') AS [B tag],
ISNULL(ppi_latest.[Offline Code], '') AS [Offline Code],
-- 4. 태그
(SELECT COUNT(*)
FROM GGCoreGGPCOM.dbo.PlayerTag pt
WHERE pt.PlayerId = p.Id) AS [tag_count],
ISNULL((SELECT STUFF((
SELECT ',' + t.Name
FROM GGCoreGGPCOM.dbo.PlayerTag pt
JOIN GGCoreGGPCOM.dbo.Tag t ON pt.TagId = t.Id
WHERE pt.PlayerId = p.Id
FOR XML PATH('')), 1, 1, '')), '') AS [Tag],
-- 5. 게임 통계
SUM(ISNULL(pgs.PokerGGR, 0)) AS [Poker GGR],
SUM(ISNULL(pgs.CasinoGGR, 0)) AS [Casino GGR],
SUM(ISNULL(pgs.FishBuffetReward, 0) + ISNULL(pgs.StreamerReward, 0)) AS [Reward Program],
SUM(ISNULL(pgs.CasinoContribution, 0)) AS [Casino Contribution],
SUM(ISNULL(pgs.ProfitAndLossPoker, 0)) AS [Poker P&L],
SUM(ISNULL(pgs.NetworkGiveaway, 0)) AS [Network Giveaway],
SUM(ISNULL(pgs.TournamentOverlayPlayerDeducted, 0)) AS [T/O],
SUM(ISNULL(pgs.RakedHands, 0)) AS [Raked Hands],
SUM(ISNULL(pgs.NonRakedHands, 0)) AS [Non Raked Hands],
SUM(ISNULL(pgs.OceanRewards, 0)) AS [Ocean Rewards],
SUM(ISNULL(pgs.OceanRewardsCostPoker, 0)) AS [Poker Reward Cost],
SUM(ISNULL(pgs.OceanRewardsCostCasino, 0)) AS [Casino Reward Cost]
FROM
GGCoreGGPCOM.dbo.Player p
LEFT JOIN
GGCoreGGPCOM.dbo.PlayerAgent pa ON p.Id = pa.PlayerId
LEFT JOIN
GGCoreGGPCOM.dbo.PlayerGameStatistics pgs ON p.AccountId = pgs.AccountId
OUTER APPLY (
SELECT TOP 1
CASE WHEN ppi.IsOfflineCode = 0 THEN ppi.BTag ELSE NULL END AS [B tag],
CASE WHEN ppi.IsOfflineCode = 1 THEN ppi.BTag ELSE NULL END AS [Offline Code]
FROM GGCoreGGPCOM.dbo.PlayerPersonalInformation ppi
WHERE ppi.PlayerId = p.Id
ORDER BY pgs.PokerGGR DESC
) AS ppi_latest
-- 조회 대상 조건입력
WHERE
[조건입력]
GROUP BY
p.Id, p.MobileNumber, p.Email, p.Username, p.Nickname, p.AssociationType, p.Site,
pa.Code, p.Country, p.AffiliateMemberId,
ppi_latest.[B tag], ppi_latest.[Offline Code]
ORDER BY
[Poker GGR] DESC;
| [SQL] 글로벌 게임 플랫폼 데이터 기반 Poker GGR 산출 로직 표준화 및 SQL 조회 가이드 구축 (0) | 2026.03.05 |
|---|---|
| [QA/자동화] 데이터 정합성 자동 검증 대시보드 구축 (0) | 2026.03.05 |
| [Redash/SQL] Redash 기반 포인트 정합성 검증 및 모니터링 구축 (0) | 2026.03.05 |
| MySQL 이벤트 스케쥴러 생성 (0) | 2025.05.09 |