SELECT 문을 살펴봅니다.

완료됨

Transact-SQL 또는 T-SQL은 Microsoft SQL 제품 및 서비스에서 사용하는 ANSI 표준 SQL 언어입니다. T-SQL은 표준 SQL과 비슷합니다. DML 문 중 옵션과 변형이 가장 많은 SELECT 문을 중점적으로 다룰 것입니다.

먼저 SELECT 문이 처리되는 방법을 좀 더 깊게 살펴봅시다. SELECT 문이 작성되는 순서는 SQL Server 데이터베이스 엔진에서 계산하고 처리하는 순서와 다릅니다.

다음과 같은 쿼리를 고려해 보세요.

SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;

쿼리는 여러 ‘절’로 구성된 SELECT 문으로 구성되며 각 절은 검색되는 데이터에 적용해야 하는 특정 작업을 정의합니다. 작업의 런타임 순서를 살펴보기 전에, 이 모듈에서 다양한 절의 세부 정보를 다루지 않지만 이 쿼리가 수행하는 작업을 간략하게 살펴보겠습니다.

SELECT 절은 OrderDate 열과 OrderID 값의 개수를 반환합니다. 이 값에는 Orders라는 이름(또는 ‘별칭’)이 할당됩니다.

SELECT OrderDate, COUNT(OrderID) AS Orders

FROM 절은 쿼리의 행의 원본인 테이블을 식별합니다. 이 경우 Sales.SalesOrder 테이블입니다.

FROM Sales.SalesOrder

WHERE 절은 결과에서 행을 필터링하여 지정된 조건을 충족하는 행만 유지합니다. 이 경우 상태가 “shipped”인 주문입니다.

WHERE Status = 'Shipped'

GROUP BY 절은 필터 조건을 충족하는 행을 가져와 OrderDate별로 그룹화하므로 OrderDate가 동일한 모든 행은 단일 그룹으로 간주되고 각 그룹에 하나의 행이 반환됩니다.

GROUP BY OrderDate

그룹을 구성한 후 HAVING 절은 고유의 조건자에 따라 그룹을 필터링합니다. 두 개 이상의 주문이 있는 날짜만 결과에 포함됩니다.

HAVING COUNT(OrderID) > 1

이 쿼리를 미리 보기 위해 최종 절은 출력을 OrderDate 기준 내림차순으로 정렬하는 ORDER BY입니다.

ORDER BY OrderDate DESC;

지금까지 각 절이 수행하는 작업을 살펴보았습니다. 이제 SQL Server가 실제로 계산하는 순서를 살펴보겠습니다.

  1. 문의 나머지 부분에 대한 원본 행을 제공하기 위해 FROM 절이 먼저 계산됩니다. 가상 테이블이 만들어지고 다음 단계로 전달됩니다.
  2. WHERE 절을 계산하여 조건자와 일치하는 원본 테이블에서 해당하는 행을 필터링합니다. 필터링된 가상 테이블이 다음 단계로 전달됩니다.
  3. Group BY는 다음으로 GROUP BY 목록에 있는 고유 값에 따라 가상 테이블의 행을 구성합니다. 그룹 목록이 포함된 새 가상 테이블이 만들어지고 다음 단계로 전달됩니다. 작업 흐름에서 이 시점부터 다른 요소에서 GROUP BY 목록 또는 집계 함수의 열만 참조할 수 있습니다.
  4. HAVING 절은 조건자를 기준으로 전체 그룹을 필터링하여 다음에 계산됩니다. 3단계에서 만든 가상 테이블이 필터링되어 다음 단계로 전달됩니다.
  5. SELECT 절은 마지막으로 실행되어 쿼리 결과에 표시될 열을 결정합니다. SELECT 절은 다른 단계 이후에 계산되므로 SELECT 절에서 만든 열 별칭(이 예제에서는 Orders)은 GROUP BY 또는 HAVING 절에서 사용할 수 없습니다.
  6. ORDER BY 절은 마지막으로 실행되어 열 목록에 의해 결정된 대로 행을 정렬합니다.

예제 쿼리에 이해한 내용을 적용하기 위해 위의 SELECT 문 런타임의 논리적 순서는 다음과 같습니다.

FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate 
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;

작성하는 모든 SELECT 문에 가능한 모든 절이 필요한 것은 아닙니다. 유일한 필수 절은 SELECT 절이며 경우에 따라 자체적으로 사용할 수 있습니다. 일반적으로 쿼리 중인 테이블을 식별하기 위해 FROM 절이 포함되어 있습니다. 또한 Transact-SQL에는 추가될 수 있는 다른 절이 있습니다.

앞서 살펴봤듯이 논리적으로 계산되는 순서와 동일한 순서로 T-SQL 쿼리를 작성하지 않습니다. 절은 이미 처리된 절에서 사용 가능하게 설정된 정보에만 액세스할 수 있기 때문에 계산의 런타임 순서에 따라 어떤 데이터가 어떤 절에서 사용 가능할지가 결정됩니다. 따라서 쿼리를 작성할 때 진정한 논리적 처리 순서를 이해하는 것이 중요합니다.

모든 열 선택

SELECT 절은 쿼리의 결과에서 반환될 값을 나열하므로 SELECT ‘목록’이라고 합니다.

SELECT 절의 가장 간단한 형태는 별표 문자(*)를 사용하여 모든 열을 반환하는 것입니다. T-SQL 쿼리에서 사용되는 경우 이를 ‘별표’라고 합니다. SELECT *는 빠른 테스트에 적합하지만, 다음과 같은 이유로 프로덕션 작업에 사용하지 않는 것이 좋습니다.

  • 테이블에 열을 추가하거나 다시 정렬하는 변경 내용은 쿼리 결과에 반영되며 이로 인해 쿼리를 사용하는 애플리케이션 또는 보고서에 대한 예기치 않은 출력이 발생할 수 있습니다.
  • 필요하지 않은 데이터를 반환하면 쿼리 속도가 느려질 수 있으며 원본 테이블에 많은 행이 포함된 경우 성능 문제가 발생할 수 있습니다.

예를 들어 다음 예에서는 (가상) Production.Product 테이블에서 모든 열을 검색합니다.

SELECT * FROM Production.Product;

이 쿼리의 결과는 테이블의 모든 행에 대한 모든 열을 포함하는 행 집합이며 다음과 같을 수 있습니다.

ProductID

Name

ProductNum

StandardCost

ListPrice

크기

무게

ProductCatID

680

HL Road Frame - Black, 58

FR-R92B-58

흑인

1059.31

1431.5

58

1016.04

18

706

HL Road Frame - Red, 58

FR-R92R-58

빨간색

1059.31

1431.5

58

1016.04

18

707

Sport-100 Helmet, Red

HL-U509-R

빨간색

13.0863

34.99

35

708

Sport-100 Helmet, Black

HL-U509

흑인

13.0863

34.99

35

...

...

...

...

...

...

...

...

...

특정 열 선택

명시적 열 목록을 사용하면 반환되는 열과 순서를 정확하게 컨트롤할 수 있습니다. 결과의 각 열에는 열 이름이 헤더로 포함됩니다.

예를 들어 가상의 Production.Product 테이블을 다시 사용하는 다음 쿼리를 살펴봅시다.

SELECT ProductID, Name, ListPrice, StandardCost
‎FROM Production.Product;

이번에는 지정된 열만 결과에 포함됩니다.

ProductID

Name

ListPrice

StandardCost

680

HL Road Frame - Black, 58

1431.5

1059.31

706

HL Road Frame - Red, 58

1431.5

1059.31

707

Sport-100 Helmet, Red

34.99

13.0863

708

Sport-100 Helmet, Black

34.99

13.0863

...

...

...

...

식 선택

SELECT 절은 지정된 테이블에 저장된 열을 검색하는 것 외에도 연산자를 사용하여 열과 값 또는 여러 열을 결합하는 계산 및 조작을 수행할 수 있습니다. 계산 또는 조작의 결과는 결과에 별도의 열로 표시되는 단일 값(스칼라) 결과여야 합니다.

예를 들어 다음 쿼리에는 두 개의 식이 포함됩니다.

SELECT ProductID,
      Name + '(' + ProductNumber + ')',
  ListPrice - StandardCost
FROM Production.Product;

이 쿼리의 결과는 다음과 같을 수 있습니다.

ProductID

680

HL Road Frame - Black, 58(FR-R92B-58)

372.19

706

HL Road Frame - Red, 58(FR-R92R-58)

372.19

707

Sport-100 Helmet, Red(HL-U509-R)

21.9037

708

Sport-100 Helmet, Black(HL-U509)

21.9037

...

...

...

결과에서 다음과 같은 몇 가지 흥미로운 사실을 확인할 수 있습니다.

  • 두 식에서 반환된 열에는 열 이름이 없습니다. 쿼리를 제출하는 데 사용하는 도구에 따라 누락된 열 이름은 빈 열 머리글, “no column name” 리터럴 지표 또는 column1과 같은 기본 이름으로 표시될 수 있습니다. 이 섹션의 후반부에 있는 쿼리에서 열 이름의 ‘별칭’을 지정하는 방법을 살펴보겠습니다.
  • 첫 번째 식은 + 연산자를 사용하여 문자열(문자 기반) 값을 연결하는 반면 두 번째 식은 - 연산자를 사용하여 한 숫자 값을 다른 숫자 값에서 뺍니다. 숫자 값과 함께 사용하는 경우 + 연산자는 더하기를 수행합니다. 식에 포함하는 열의 ‘데이터 형식’을 이해하는 것이 분명히 중요합니다. 다음 섹션에서는 데이터 형식에 대해 설명합니다.

열 별칭 지정

SELECT 쿼리에서 반환하는 각 열에 원본 열 이름 대신 ‘별칭’을 지정하거나 식의 출력에 이름을 할당할 수 있습니다.

예를 들어 다음 쿼리는 앞의 쿼리와 동일하지만 각 열에 대해 지정된 별칭을 사용합니다.

SELECT ProductID AS ID,
      Name + '(' + ProductNumber + ')' AS ProductName,
  ListPrice - StandardCost AS Markup
FROM Production.Product;

이 쿼리의 결과에는 지정된 열 이름이 포함됩니다.

ID

ProductName

태그

680

HL Road Frame - Black, 58(FR-R92B-58)

372.19

706

HL Road Frame - Red, 58(FR-R92R-58)

372.19

707

Sport-100 Helmet, Red(HL-U509-R)

21.9037

708

Sport-100 Helmet, Black(HL-U509)

21.9037

...

...

...

참고

AS 키워드는 별칭을 지정할 때 선택 사항이지만 설명을 위해 포함하는 것이 좋습니다.

서식 지정 쿼리

이 섹션의 예제를 통해 쿼리 코드의 형식을 유연하게 지정할 수 있다는 것을 확인할 수 있습니다. 예를 들어 각 절(또는 전체 쿼리)을 한 줄에 작성하거나 여러 줄로 나눌 수 있습니다. 대부분의 데이터베이스 시스템에서 코드는 대/소문자를 구분하지 않으며 T-SQL 언어의 일부 요소는 선택 사항입니다(앞에서 설명한 대로 AS 키워드가 포함되며 문 끝의 세미콜론도 포함).

T-SQL 코드를 쉽게 읽을 수 있도록(따라서 더 쉽게 이해하고 디버그할 수 있도록) 다음 지침을 고려합니다.

  • SELECT, FROM, AS와 같은 T-SQL 키워드를 대문자로 표시합니다. 키워드를 대문자로 표시하는 것은 복잡한 문에서 각 절을 더 쉽게 찾을 수 있도록 일반적으로 사용되는 규칙입니다.
  • 명령문의 각 주 절에서 새 줄을 시작합니다.
  • SELECT 목록에 적지 않은 열, 식 또는 별칭이 포함된 경우 각 열을 각각의 줄에 나열하는 것이 좋습니다.
  • 하위 절 또는 열이 포함된 줄을 들여쓰기하여 각 주 절에 속하는 코드를 명확하게 합니다.