데이터베이스에서 행을 검색하고 SQL Server에서 하나 이상의 테이블에서 하나 이상의 행 또는 열을 선택할 수 있도록 한다.
SELECT 문의 전체 구문은 복잡하지만 절은 아래와 같이 요약할 수 있다.
● SELECT
<select_criteria> ::=
[ TOP ( top_expression ) ]
[ ALL | DISTINCT ]
{ * | column_name | expression } [ ,...n ]
[ FROM { table_source } [ ,...n ] ]
[ WHERE <search_condition> ]
[ GROUP BY <group_by_clause> ]
[ HAVING <search_condition> ]
[ ORDER BY <order_by_expression> ]
[ OPTION ( <query_option> [ ,...n ] ) ]
위의 구문은 SQL Server Docs에 명시된 내용이다.
● SELECT 문의 논리적 처리 순서
SELECT 문의 논리적 처리 순서(바인딩 순서)는 아래와 같다.
- FROM
- ON
- JOIN
- WHERE
- GROUP BY
- WITH CUBE or WITH ROLLUP
- HAVING
- SELECT
- DISTINCT or ALL
- ORDER BY
- TOP
위 순서는 옵티마이저가 SQL 문장의 SYNTAX, SEMANTIC 에러를 점검하는 순서이기도 하다. 예를 들면 FROM 절에 정의되지 않은 테이블의 칼럼을 WHERE 절, GROUP BY 절, HAVING 절, SELECT 절, ORDER BY 절에서 사용하면 에러가 발생한다.
그러나 ORDER BY 절에는 SELECT 목록에 나타나지 않은 문자형 항목이 포함될 수 있다. 단 SELECT DISTINCT를 지정하거나 SQL 문장에 GROUP BY 절이 있거나, SELECT 문에 UNION 연산자가 있으면 열 정의가 SELECT 목록에 표시돼야 한다.
이 부분은 관계형 데이터베이스가 데이터를 메모리에 올릴 때 행 단위로 모든 칼럼을 가져오게 되므로, SELECT 절에서 일부 컬럼만 선택하더라도 ORDER BY 절에서 메모리에 올라와 있는 다른 칼럼의 데이터를 사용할 수 있다.
※ 참고
위의 순서는 일반적으로 맞지만, 순서가 달라지는 특수한 경우가 있을 수 있다.
예를 들어 테이블에 클러스터형 인덱스가 있고, SELECT 열 목록에서 VARCHAR 데이터 형식을 정수로 바꾸는 CONVERT를 사용한다고 가정해보자.
이런 상황에서 CONVERT는 WHERE 문이 실행되기 전에 실행될 수 있다고 한다.
● 예제 ( AdventureWorks )
A. SELECT를 사용하여 행 및 열 검색
이 섹션에서는 세 가지 코드 예를 보여 줍니다. 첫 번째 코드 예에서는 DimEmployee 테이블에서 모든 행(WHERE 절이 지정되지 않음) 및 모든 열(* 사용)을 반환합니다.
SELECT *
FROM DimEmployee
ORDER BY LastName;
이 다음 예제에서는 테이블 별칭을 사용하여 같은 결과를 냅니다.
SELECT e.*
FROM DimEmployee AS e
ORDER BY e.LastName;
다음 예에서는 AdventureWorksPDW2012 데이터베이스의 DimEmployee 테이블에서 모든 행(WHERE 절이 지정되지 않음) 및 열의 하위 집합(FirstName, LastName, StartDate)을 반환합니다. 세 번째 열 머리글 이름이 FirstDay로 변경됩니다.
SELECT FirstName, LastName, StartDate AS FirstDay
FROM DimEmployee
ORDER BY LastName;
이 예제에서는 EndDate가 NULL이 아니며 MaritalStatus가 'M'(기혼)인 DimEmployee의 행만 반환합니다.
SELECT FirstName, LastName, StartDate AS FirstDay
FROM DimEmployee
WHERE EndDate IS NOT NULL
AND MaritalStatus = 'M'
ORDER BY LastName;
B. SELECT에 열 머리글 및 계산 사용
다음 예제에서는 DimEmployee 테이블의 모든 행을 반환하며 BaseRate 및 40시간 근무 주를 기준으로 각 직원의 총 급여를 계산합니다.
SELECT FirstName, LastName, BaseRate, BaseRate * 40 AS GrossPay
FROM DimEmployee
ORDER BY LastName;
C. SELECT에 DISTINCT 사용
다음 예제에서는 DISTINCT를 사용하여 DimEmployee 테이블의 모든 고유한 이름 목록을 생성합니다.
SELECT DISTINCT Title
FROM DimEmployee
ORDER BY Title;
D. GROUP BY 사용
다음 예제에서는 일별 총 판매액을 모두 찾습니다.
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;
GROUP BY 절을 사용했으므로 각 날짜에 대해 모든 판매의 합계를 포함하는 한 행만 반환됩니다.
E. GROUP BY에 여러 그룹 사용
다음 예제에서는 주문일과 프로모션 키별로 그룹화된 일별 총 인터넷 판매 합계와 평균 금액을 찾습니다.
SELECT OrderDateKey, PromotionKey, AVG(SalesAmount) AS AvgSales, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey, PromotionKey
ORDER BY OrderDateKey;
F. GROUP BY 및 WHERE 사용
다음 예에서는 가격이 주문일이 2002년 8월 1일 이후인 행만 검색한 후 그 결과를 그룹화합니다.
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
WHERE OrderDateKey > '20020801'
GROUP BY OrderDateKey
ORDER BY OrderDateKey;
G. GROUP BY에 식 사용
다음 예에서는 식으로 그룹화를 수행합니다. 식에 집계 함수가 없는 경우 식으로 그룹화를 수행할 수 있습니다.
SELECT SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY (OrderDateKey * 10);
H. GROUP BY 및 ORDER BY 사용
다음 예제에서는 일별 판매 합계와 일별 주문을 찾습니다.
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey;
I. HAVAING 절 사용
이 쿼리에서는 HAVING 절을 사용하여 결과를 제한합니다.
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
HAVING OrderDateKey > 20010000
ORDER BY OrderDateKey;
'DataBase > SQLD,SQLP' 카테고리의 다른 글
[MSSQL] 윈도우 함수 ROW_NUMBER() 순차번호 할당 (0) | 2022.05.04 |
---|---|
[MSSQL] 윈도우 함수 RANK() OVER 다루기 / DENSE_RANK() (0) | 2022.05.04 |
[MSSQL] 집합 연산자 (0) | 2022.05.02 |
[MSSQL] 서브 쿼리 SubQuery (0) | 2022.05.01 |
[SQLD/SQLP] SQL 이란? (0) | 2022.02.22 |