MSSQL Scalar subquery
Subquery
- SQL문 안에 있는 SQL문을 의미한다.
● 소괄호로 감싸 사용한다.
● 서브쿼리 안에서는 ORDER BY를 사용하지 못한다.
Scalar subquery
- 한 레코드에 한 값만을 반환하는 서브쿼리를 의미한다.
● 조인 키 값의 종류가 한정적이고 동일한 것이 많을 때 주로 사용한다.
● 장점으로는 캐시효과. 단점으로는 반복수행이다.
● 캐시효과로 인해 데이터가 적을 때 유리하지만 데이터가 많을 때는 반복수행으로 오히려 성능이 더 떨어진다.
Hackerrank의 New Companies를 예제로 하였다.
예제 데이터는 밑에 준비해두었다.
DECLARE @COMPANY TABLE
(
COMPANY_CODE NVARCHAR(30)
, FOUNDER NVARCHAR(100)
)
DECLARE @LEAD_MANAGER TABLE (
LEAD_MANAGER_CODE NVARCHAR(30)
, COMPANY_CODE NVARCHAR(30)
)
DECLARE @SENIOR_MANAGER TABLE (
SENIOR_MANAGER_CODE NVARCHAR(30)
, LEAD_MANAGER_CODE NVARCHAR(30)
, COMPANY_CODE NVARCHAR(30)
)
DECLARE @MANAGER TABLE (
MANAGER_CODE NVARCHAR(30)
, SENIOR_MANAGER_CODE NVARCHAR(30)
, LEAD_MANAGER_CODE NVARCHAR(30)
, COMPANY_CODE NVARCHAR(30)
)
DECLARE @EMPLOYEE TABLE (
EMPLOYEE_CODE NVARCHAR(30)
, MANAGER_CODE NVARCHAR(30)
, SENIOR_MANAGER_CODE NVARCHAR(30)
, LEAD_MANAGER_CODE NVARCHAR(30)
, COMPANY_CODE NVARCHAR(30)
)
INSERT INTO @COMPANY VALUES('C1','Monika')
INSERT INTO @COMPANY VALUES('C2','Samantha')
INSERT INTO @LEAD_MANAGER VALUES('LM1','C1')
INSERT INTO @LEAD_MANAGER VALUES('LM2','C2')
INSERT INTO @SENIOR_MANAGER VALUES('SM1','LM1','C1')
INSERT INTO @SENIOR_MANAGER VALUES('SM2','LM1','C1')
INSERT INTO @SENIOR_MANAGER VALUES('SM3','LM2','C2')
INSERT INTO @MANAGER VALUES ('M1','SM1','LM1','C1')
INSERT INTO @MANAGER VALUES ('M2','SM2','LM2','C2')
INSERT INTO @MANAGER VALUES ('M3','SM3','LM2','C2')
INSERT INTO @EMPLOYEE VALUES ('E1','M1','SM1','LM1','C1')
INSERT INTO @EMPLOYEE VALUES ('E2','M1','SM1','LM1','C1')
INSERT INTO @EMPLOYEE VALUES ('E3','M2','SM2','LM2','C2')
INSERT INTO @EMPLOYEE VALUES ('E4','M3','SM3','LM2','C2')
< 조건> 에는
- 아래의 테이블 스키마를 참조하여
COMPANY_CODE(회사코드)
FOUNDER(설립자)
TOTAL NUMBER OF LEAD_MANAGERS(총 리드 매니저 수)
TOTAL NUMBER OF SENIOR_MANAGERS(총 시니어 매니저 수)
TOTAL NUMBER OF MANAGERS(총 매니저 수)
TOTAL NUMBER OF EMPLOYEES(총 직원 수)
를 출력하기 위한 SQL문을 작성하세요.
- COMPANY_CODE 오름차순으로 정렬하세요.
< 메모 >에는
- 테이블에는 중복된 레코드가 포함될 수 있습니다.
- COMPANY_CODE가 문자열이므로 정렬은 숫자일 수 없습니다.
예를 들어, COMPANY_CODE가 C1,C2,C10이면 오름차순으로 정렬했을 때 COMPANY_CODE는 C1,C10,C2가 됩니다.
이러한 전제가 있을 때 고려해야 할 사항은
- 각 매니저와 직원을 COUNT해야한다.
- 중복된 레코드에 대하여 중복제거를 해야 한다.
나는 Scalar subquery를 이용해 아래와 같이 문제를 풀었다.
SELECT
A.COMPANY_CODE
, A.FOUNDER
, (SELECT COUNT(*) FROM ( SELECT DISTINCT * FROM @LEAD_MANAGER WHERE COMPANY_CODE = A.COMPANY_CODE) A)
, (SELECT COUNT(*) FROM ( SELECT DISTINCT * FROM @SENIOR_MANAGER WHERE COMPANY_CODE = A.COMPANY_CODE) A)
, (SELECT COUNT(*) FROM ( SELECT DISTINCT * FROM @MANAGER WHERE COMPANY_CODE = A.COMPANY_CODE) A)
, (SELECT COUNT(*) FROM ( SELECT DISTINCT * FROM @EMPLOYEE WHERE COMPANY_CODE = A.COMPANY_CODE) A)
FROM @COMPANY A
ORDER BY A.COMPANY_CODE
하지만 이 외에도 풀 수 있는 방법은 많다.
DISTINCT 대신 GROUP BY를 활용할 수도 있고, Scalar subquery 대신 JOIN을 활용할 수 있다.