티스토리 뷰

Entity Framework Core

SQL Style Guide (ko-KR)

kaki104 2021. 4. 27. 10:15
반응형

SQL Style Guide를 작성해야해서 검색을 좀 해보았습니다. 

Microsoft에서는 SQL 스타일 가이드와 같은 문서가 없습니다. 다만, 예제 소스를 보고 어떻게 만드는지 파악을 할 수 있는 정도 입니다.

SQL style guide by Simon Holywell
이 스타일 가이드가 좀 오래되었고, Star와 Fork가 많은데.. 컬럼 이름을 모두 소문자로 사용하고 있어서.. 마음에 들지 않습니다;;
Modern SQL Style Guide (github.com)
이 스타일 가이드는 컬럼 이름을 모두 PascalCase를 사용해서 표시합니다. 대신 keyword를 모두 소문자로 사용합니다. 

스타일 가이드는 Modern SQL Style Guid를 기본으로 키워드만 대문자로 변경하는 방향으로 스타일 가이드를 만들도록 하겠습니다.

Purpose

스타일 가이드는 SQL 문을 쉽게 작성하고 읽기 쉽고 유지하기 쉽고 아름답게 볼 수 있도록 설계되었습니다. 이 문서는 팀의 선호하는 SQL 스타일을 기록하려는 모든 사람을 위한 가이드로 사용됩니다.

 

이 가이드 라인 세트를 사용하거나 포크를 사용하거나 자신만의 스타일 가이드를 만드십시오. 여기서 핵심은 스타일을 선택하고 그것에 살을 붙이는 것입니다. 모든 사람들을 행복하게 만들 확률은 낮기 때문에 선택적으로 사용하시기 바랍니다.

 

이 가이드를 프로젝트의 코드 기반의 일부로 포함 시키거나 프로젝트의 모든 사람이 자유롭게 읽을 수 있도록 참조하십시오.

 

이 안내서는 http://www.sqlstyle.guide킥 스타터 가이드를 포함하여 SQL 표준의 다양한 시도를 기반으로합니다. 기원으로 인해 Creative Commons Attribution-ShareAlike 4.0 국제 라이센스로 라이센스가 부여됩니다.

 

사용 된 SQL 문 예제는 AdventureWorks 데이터베이스의 테이블을 기반으로합니다. 기존의 AdventureWorks 스키마를 사용하기 때문에이 문서의 지침 중 일부는 항상 준수 할 수 없습니다. 특히 명명 규칙과 관련이 없습니다. 그러한 불일치는 보이는 대로 설명을 하도록 하겠습니다.

 

참고 :이 스타일 가이드는 Microsoft SQL Server와 함께 사용할 수 있지만 일부 간단한 수정으로 모든 SQL 데이터베이스에 적용 할 수 있습니다.

Principles

  • 우리는 규율 있고 실용적인 코드 작성 접근법을 취합니다.
  • 우리는 소스 제어, 피어 검토 및 제대로 유지 관리되는 다른 소스 코드와 마찬가지로 SQL을 처리합니다.
  • 우리는 스타일의 일관성이 중요하다고 생각하며, 장인 정신을 중시하지만, 다른 실제적인 관심사를 배제하는 것은 아닙니다.
  • 우리는 코드에서 명확한 구조와 필요한 경우 주석을 통해 의도를 명시적으로 보여줄 것입니다.
  • 우리는 수기로 작성된 SQL에 대한 일관된 스타일을 고수하여 많은 작성자, 편집자 및 독자가 있는 환경에서 코드를 쉽게 이해할 수 있도록 합니다.

Quick look

모든 세부 사항에 들어가기 전에 이 스타일 가이드의 권장 사항과 일치하는 포맷 된 아름다운 SQL을 보여주는 몇 가지 예가 있습니다.

-- BASIC SELECT EXAMPLE
SELECT p.Name AS ProductName
     , p.ProductNumber
     , pm.Name AS ProductModelName
     , p.Color
     , p.ListPrice
  FROM Production.Product AS p
  JOIN Production.ProductModel AS pm
    ON p.ProductModelID = pm.ProductModelID
 WHERE p.Color IN ('Blue', 'Red')
   AND p.ListPrice < 800.00
   AND pm.Name LIKE '%frame%'
 ORDER BY p.Name
 -- BASIC INSERT EXAMPLE
INSERT INTO Sales.Currency (CurrencyCode, [Name], ModifiedDate)
VALUES ('XBT', 'Bitcoin', GETUTCDATE())
     , ('ETH', 'Ethereum', GETUTCDATE())
-- BASIC UPDATE EXAMPLE
UPDATE p
   SET p.ListPrice = p.ListPrice * 1.05
     , p.ModifiedDate = GETUTCDATE()
  FROM Production.Product AS p
 WHERE p.SellEndDate IS NULL
   AND p.SellStartDate IS NOT NULL
-- BASIC DELETE EXAMPLE
DELETE cc
  FROM Sales.CreditCard AS cc
 WHERE cc.ExpYear < '2003'
   AND cc.ModifiedDate < DATEADD(YEAR, -1, GETUTCDATE())

Rules

General guidance

  • 쿼리를 빠르고 쉽게 검색할 수 있도록 수직 정렬에 "river"를 사용하는 것을 선호합니다.
  • 쿼리 또는 스크립트의 맨 위에는 주석이 표시되어야하며 메커니즘이 아닌 쿼리의 의도를 설명해야합니다.
  • 쿼리에 대해 명확하지 않은 사항(예: 특정 필터가 필요한 이유, 최적화 트릭이 필요한 이유 등)에 대해 설명하십시오.
  • 서술적 과잉성을 선호합니다.
  • GOOD: SELECT emp.LoginID AS EmployeeUserName
  • BAD: SELECT emp.LoginID AS EmpUsrNm
  • 이 스타일 가이드를 적용하기 전에 생성된 스크립트는 기존 스타일을 따르십시오. SQL 스크립트는 하나의 명확한 스타일을 가져야 하며, 전체 스크립트를 동일한 스타일을 준수하도록 변경하지 않는 한 이러한 규칙을 기존 스크립트에 적용해서는 안 됩니다.
  • 시간대 정보 (DateTimeOffset)를 포함하지 않는 한 UTC에 datetimedatetime2를 저장하면 시간이 분명하고 변환 할 수 있습니다. 날짜/시간 데이터를 참조 할 때 ISO-8601 호환 시간 및 날짜 정보 (YYYY-MM-DD HH : MM : SS.SSSSS)를 사용하십시오.

Naming guidance

이름은 underscore_sepasrated 또는 PascalCase 여야하지만 스타일을 섞지 마십시오.

GOOD: SELECT COUNT(*) AS the_tally, SUM(*) AS the_total ...

BAD: SELECT COUNT(*) AS The_Tally, SUM(*) as theTotal ...

Tables

  • 가능한 경우 테이블 이름에 예약어를 사용하지 마십시오.
  • 테이블의 이름을 지정하기 위해 일반적으로 이해되는 가장 짧은 단어를 사용합니다.
  • 복수형을 테이블 이름에 지정하면 테이블을 더 쉽게 알 수 있습니다. (예를 들어, Employees over Employee)
  • 개체 접두사 또는 헝가리 표기법 사용 안 함. (예를 들어, sp_, prc_, vw_, tbl_, t_, fn_, etc)
  • 의미 접두사가 있는 테이블은 특성을 이해하는데 도움이 된다면 사용해도 괜찮습니다. (예를 들어 데이터 웨어하우스에서 DimFact와 같은 접두사를 사용하는 것이 일반적입니다.)
  • 테이블을 컬럼 중 하나와 동일한 이름으로 만들지 마십시오.
  • Many-to-many join 테이블을 만들 때 테이블의 이름을 연결해서 사용합니다.
    • GOOD: drivers_xref_cars
    • BAD: drivers_cars
  • 테이블은 항상 기본 키가 있어야합니다. 단일 컬럼, 자동 번호(identity) 대리 키가 바람직합니다.
  • Natural 키 또는 복합 키를 primary 키로 사용하는 대신 unique 제약 조건으로 사용합니다.
  • 복합 키는 세부적이고 느린 외래 키 조인을 위한 것입니다. int/bigint 기본 키는 테이블이 커지면 외래 키로서 최적입니다.
  • 테이블은 항상 created_atupdated_at 메타 데이터 필드를 사용하여 시스템간에 데이터 이동을 쉽게 할 수 있습니다 (ETL). 또한 삭제 된 레코드를 아카이브 테이블에 저장하거나 소프트 삭제를위한 deleted_at 필드를 갖는 것을 고려하십시오.
  • 모델을 설계할 때 데이터 분석가와 ETL 개발자의 요구를 잊지 마십시오.
  • ETL : Extraction, Transformation, and Loading)

Columns

  • 가능한 경우 열 이름에 예약어를 사용하지 마십시오.
  • 가능한 경우 테이블의 기본 식별자의 이름으로 id를 사용하지 마십시오.
  • 테이블과 동일한 이름으로 열을 추가하지 마십시오. 그 반대의 경우도 마찬가지입니다.
  • Name, Description, 등과 같은 일반적인 단어를 피하십시오. 이 단어의 설명 접두사를 선호하여 비슷한 이름의 열에 다른 테이블에 가입 할 때 별칭이 필요하지 않습니다. (주: 이 안내서는 일반적으로 이 가이드의 조언에 대해 이름이 지정된 열이있는 AdventureWorks 데이터베이스를 사용합니다. 기존 컨벤션이 귀하의 통제를 벗어난 곳에 있을 수 있습니다.)
  • Description의 약어로 Desc을 사용하지 마십시오. 전체 단어를 쓰거나 키워드가 아닌 다른 단어를 사용하십시오.

Aliases

  • 별칭은 지정 중인 개체 또는 표현식과 어떤 방식으로든 관련되어야 합니다.
  • 일반적으로 별칭은 개체 이름에 있는 각 단어의 첫 글자가 좋은 약어일 수 있습니다.
  • 동일한 이름의 별칭이 이미있는 경우 숫자를 추가합니다.
  • 하위 쿼리를 사용할 경우 외부 쿼리의 별칭과 구별하기 위해 _로 별칭을 접두사로 지정합니다.
  • 항상 AS 키워드를 포함하십시오. 쿼리가 쉽게 읽을 수 있고 명시 적입니다.
  • 계산된 데이터(예, SUM() 또는 AVG())의 경우 스키마에서 정의된 열이면 이름을 지정합니다.

Whitespace

탭이 없습니다. 들여 쓰기에 대한 공간을 사용하십시오.

편집기를 들여쓰기당 4칸으로 구성하되, SQL이 "river"로 들여쓰기하고, 들여쓰기 증분 설정은 사용하지 않도록 합니다.

후행 공백이 없습니다.

문 사이에 빈 줄이 세 개 이하입니다.

단일 문의 중간에 빈 줄이 없습니다.

파일 끝에 있는 빈 줄 하나

SQL 편집기가 지원하는 경우 합리적인 공백 규칙을 적용하려면 .editorconfig 파일을 사용하십시오.

# .editorConfig is awesome: https://EditorConfig.org

# SQL files
[*.{sql,tsql,ddl}]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = crlf
trim_trailing_whitespace = true
insert_final_newline = true

River formatting

루트 키워드가 모두 동일한 문자 경계에서 끝나도록 코드를 정렬하는 데 공백을 사용할 수 있습니다. 이것은 중간에 "river"을 형성하여 독자들이 쉽게 코드를 스캔하고 구현 세부사항에서 키워드를 분리할 수 있도록 합니다. 단, River는 타이포그래피에는 좋지 않습니다. Celko의 책에서는 river을 사용하여 질문을 수직으로 정렬하는 방법을 설명합니다. 당신이 river를 사용하기로 선택한 경우 키워드를 river의 오른쪽에 맞추십시오. 하위 쿼리는 자신의 river을 만들어야합니다.

-- a river in the 7th column helps vertical readability
SELECT prdct.Name AS ProductName
     , prdct.ListPrice
     , prdct.Color
     , cat.Name AS CategoryName
     , subcat.Name AS SubcategoryName
  FROM Production.Product AS prdct
  LEFT JOIN Production.ProductSubcategory AS subcat
    ON prdct.ProductSubcategoryID = subcat.ProductSubcategoryID
  LEFT JOIN Production.ProductCategory AS cat
    ON subcat.ProductCategoryID = cat.ProductCategoryID
 WHERE prdct.ListPrice <= 1000.00
   AND prdct.ProductID NOT IN (
           SELECT _pd.ProductID
             FROM Production.ProductDocument _pd
            WHERE _pd.ModifiedDate < DATEADD(YEAR, -1, GETUTCDATE())
       )
   AND prdct.Color IN ('Black', 'Red', 'Silver')
 ORDER BY prdct.ListPrice DESC, prdct.Name
-- alternately, a river in the a different column is fine if that is preferred
-- due to longer keywords, but know that indenting can feel "off" if the
-- `select` is not in the first column for the query
   SELECT prdct.Name AS ProductName
        , prdct.ListPrice
        , prdct.Color
        , cat.Name AS CategoryName
        , subcat.Name AS SubcategoryName
     FROM Production.Product AS prdct
LEFT JOIN Production.ProductSubcategory AS subcat
       ON prdct.ProductSubcategoryID = subcat.ProductSubcategoryID
LEFT JOIN Production.ProductCategory AS cat
       ON subcat.ProductCategoryID = cat.ProductCategoryID
    WHERE prdct.ListPrice <= 1000.00
      AND prdct.ProductID NOT IN (
              SELECT _pd.ProductID
                FROM Production.ProductDocument _pd
               WHERE _pd.ModifiedDate < DATEADD(YEAR, -1, GETUTCDATE())
          )
      AND prdct.Color IN ('Black', 'Red', 'Silver')
 ORDER BY prdct.ListPrice DESC, prdct.Name

Indent formatting

River를 사용하는 것은 힘들 수 있으므로, 팀원들이 이 정렬을 선호하지 않는다면, 강을 대신하여 표준 4개의 공간 들여쓰기를 사용할 수 있습니다.

 

절을 시작하는 주요 키워드는 자신의 줄을 사용해야 합니다. 주요 키워드는 다음과 같습니다.

  • Select statement
    • SELECT
    • INTO
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • ORDER BY
  • Insert statement additions
    • INSERT INTO
    • VALUES
  • Update statement additions
    • UPDATE
    • SET
  • Delete statement additions
    • DELETE

다른 모든 키워드는 부차적인 것이므로 들여쓰기 후에 나타나야 하며 한 줄만 차지해서는 안 됩니다. 이 섹션 이외에는 이 가이드가 "River" 형식 지정 예를 계속 보여 줍니다.

-- Editors tend to handle indenting style better than river alignment. River
-- formatting has advantages over indent formatting, but this style is
-- acceptable.
SELECT
    prdct.Name AS ProductName
    ,prdct.ListPrice
    ,prdct.Color
    ,cat.Name AS CategoryName
    ,subcat.Name AS SubcategoryName
FROM
    Production.Product AS prdct
    LEFT JOIN Production.ProductSubcategory AS subcat
        ON prdct.ProductSubcategoryID = subcat.ProductSubcategoryID
    LEFT JOIN Production.ProductCategory as cat
        ON subcat.ProductCategoryID = cat.ProductCategoryID
WHERE
    prdct.ListPrice <= 1000.00
    AND prdct.Color IN ('Black', 'Red', 'Silver')
ORDER BY
    prdct.ListPrice DESC, prdct.Name

select clause

동일한 행에서 첫 번째 열을 선택하고 첫 번째 행이 고유한 열을 가져온 후 모든 후속 열을 정렬합니다.

SELECT prdct.Color
     , cat.Name AS CategoryName
     , COUNT(*) AS ProductCount
  FROM ...

세 개 이하의 열을 선택하고 짧은 이름을 가지며 별칭이 필요하지 않은 경우 간략하게 동일한 행을 사용하도록 할 수 있습니다.

-- shortcut for small columns
SELECT p.Color, c.Name, p.ListPrice
  FROM ...

Distinct 또는 top과 같은 선택 한정자를 사용하는 경우 첫 번째 열을 자체 줄에 배치합니다.

-- treat the first column differently when using distinct and top
SELECT DISTINCT
       p.Color
     , c.Name AS CategoryName
  FROM ...

접미사가 아닌 쉼표를 접두사로 사용합니다. 이는 다음과 같은 이유로 선호됩니다.

  • 이렇게 하면 열 목록의 끝에 새 열을 쉽게 추가할 수 있으며, 이는 시작 열보다 일반적입니다.
  • 그것은 의도하지 않은 앨리어싱 버그 (쉼표 없음)를 방지합니다.
  • 끝에 컬럼을 쉽게 덧붙일 수 있습니다
  • 문이 윈도우 설정 기능 및 사례 문과 같은 여러 줄을 사용하는 경우 접두사 쉼표로 새 열이 시작될 때 이를 명확히 알 수 있습니다.
  • 가독성에 악영향을 미치지 않습니다.

콤마는 키워드 쪽에서 "river"와 경계를 이루어야 합니다.

GOOD:

SELECT Name
     , ListPrice
     , Color
     , CategoryName
   ...

BAD:

SELECT Name,
       ListPrice
       Color,
       CategoryName
   ...

항상 as를 사용하여 열 이름을 변경합니다. as 문장은 다음 줄에 사용하거나 아래와 같이 사용합니다.

GOOD:

SELECT prdct.Color AS ProductColor
     , cat.Name    AS CategoryName
     , COUNT(*)    AS ProductCount
  FROM ...
...

BAD:

SELECT prdct.Color ProductColor
     , cat.Name CategoryName
     , COUNT(*) ProductCount
  FROM ...
...

항상 Aggregate, 파생 열(예: case statement) 및 함수 줄바꿈 열의 이름을 변경합니다.

SELECT ProductName
     , SUM(UnitPrice * OrderQty) AS TotalCost
     , GETUTCDATE() AS NowUTC
  FROM ...

둘 이상의 테이블에서 쿼리할 때는 항상 모든 열에 대해 테이블 별칭 접두사를 사용하십시오. 단일 문자 별칭은 일부 테이블에서는 괜찮지만 쿼리가 증가할수록 명확하지 않습니다.

SELECT prdct.Color
     , subcat.Name AS SubcategoryName
     , COUNT(*) as ItemCount
  FROM Production.Product AS prdct
  LEFT JOIN Production.ProductSubcategory AS subcat
    ON ...

이름에 키워드 충돌이 있거나 올바른 자격 증명 없이 구문 오류가 발생할 수 있는 경우가 아니면 테이블 또는 열 이름을 괄호로 묶지 마십시오.

GOOD:

-- owner and status are keywords
SELECT Title
     , [Owner]
     , [Status]
  FROM Production.Document

BAD:

-- extra brackets are messy and unnecessary
SELECT [Title]
     , [Owner]
     , [Status]
  FROM Production.Document

Windowing functions

긴 윈도우 기능은 river와 정렬된 각 절마다 하나씩 여러 줄로 분할해야 합니다. 파티션 키는 동일한 줄을 공유하거나 분할할 수 있습니다. desc은 직관적인 기본값이기 때문에 명시적 as를 사용할 필요는 없지만 설명은 필요하지 않습니다. 모든 윈도우 기능은 별칭 관계여야 합니다.

SELECT p.ProductID
     , p.Name AS ProductName
     , p.ProductNumber
     , p.ProductLine
     , ROW_NUMBER() OVER (PARTITION BY p.ProductLine
                                     , LEFT(p.ProductNumber, 2)
                              ORDER BY RIGHT(p.ProductNumber, 4) DESC) AS SequenceNum
     , p.Color
  FROM Production.Product AS p
 ORDER BY p.ProductLine
     , LEFT(p.ProductNumber, 2)
     , SequenceNum

case statements

case문은 구분하는 것이 항상 쉬운 것은 아니지만 when, then, elsecaseend 문 사이에 정렬합니다.

 

when, then, else는 라인을 유지하도록 합니다.

SELECT dep.Name AS DepartmentName
     , CASE WHEN dep.Name IN ('Engineering', 'Tool Design', 'Information Services')
            THEN 'Information Technology'
            ELSE dep.GroupName
       END AS NewGroupName
  FROM HumanResources.Department AS dep
 ORDER BY NewGroupName, DepartmentName

from clause

테이블 한 개만 있어야 합니다. 조인에서 분리된 쉼표를 사용하지 마십시오.

GOOD:

SELECT cust.AccountNumber
     , sto.Name AS StoreName
  FROM Sales.Customer AS cust
  JOIN Sales.Store AS sto
    ON cust.StoreID = sto.BusinessEntityID
...

BAD:

SELECT cust.AccountNumber
     , sto.Name AS StoreName
  FROM Sales.Customer AS cust, Sales.Store AS sto
 WHERE cust.StoreID = sto.BusinessEntityID
...

테이블을 결합할 때 외부 단어인 Inner 또는 Outer를 사용하지 않는 것이 좋습니다. 정렬이 없으면 조회를 더 쉽게 이해할 수 없으며 전체 테이블 목록을 너무 많이 변형하지 않고 스캔하기가 더 쉽습니다.

GOOD:

-- this is easier to format and read
   SELECT *
     FROM HumanResources.Employee AS emp
     JOIN Person.Person AS per
       ON emp.BusinessEntityID = per.BusinessEntityID
LEFT JOIN HumanResources.EmployeeDepartmentHistory AS edh
       ON emp.BusinessEntityID = edh.BusinessEntityID
LEFT JOIN HumanResources.Department AS dep
       ON edh.DepartmentID = dep.DepartmentID

BAD:

-- verbosity for the sake of verbosity is not helpful
-- `join` by itself always means `inner join`
-- `outer` is an unnecessary optional keyword
         SELECT *
           FROM HumanResources.Employee AS emp
     INNER JOIN Person.Person AS per
             ON emp.BusinessEntityID = per.BusinessEntityID
LEFT OUTER JOIN HumanResources.EmployeeDepartmentHistory AS edh
             ON emp.BusinessEntityID = edh.BusinessEntityID
LEFT OUTER JOIN HumanResources.Department AS dep
             ON edh.DepartmentID = dep.DepartmentID

on 키워드 및 조건은 자체 줄에서 이동할 수 있지만 조인 회선에서 일치하는 경우 스캔하는 것이 더 쉽습니다. 이것은 수용 가능한 스타일의 대안입니다.

-- this is an easier format to scan visually, but comes at the cost of longer
-- lines of code.
   SELECT *
     FROM HumanResources.Employee AS emp
     JOIN Person.Person AS per                            ON emp.BusinessEntityID = per.BusinessEntityID
LEFT JOIN HumanResources.EmployeeDepartmentHistory AS edh ON emp.BusinessEntityID = edh.BusinessEntityID
LEFT JOIN HumanResources.Department AS dep                ON edh.DepartmentID = dep.DepartmentID
...

join에있는 추가 필터는 새들 들여 쓰기 된 줄을 이동합니다. 키워드를 사용하여 줄을 올려 놓습니다.

GOOD:

   SELECT emp.JobTitle
     FROM HumanResources.Employee AS emp
LEFT JOIN HumanResources.EmployeeDepartmentHistory AS edh
       ON emp.BusinessEntityID = edh.BusinessEntityID
LEFT JOIN HumanResources.Department AS dep
       ON edh.DepartmentID = dep.DepartmentID
      AND dep.Name <> dep.GroupName  -- multi-conditions start a new line
    WHERE dep.DepartmentID IS NULL

BAD:

   SELECT emp.JobTitle
     FROM HumanResources.Employee AS emp
LEFT JOIN HumanResources.EmployeeDepartmentHistory AS edh
       ON emp.BusinessEntityID = edh.BusinessEntityID
LEFT JOIN HumanResources.Department AS dep
       ON edh.DepartmentID = dep.DepartmentID AND dep.Name <> dep.GroupName  -- needs a new line
    WHERE dep.DepartmentID IS NULL

inner join으로 시작한 다음 left join을 나열하고 필요하지 않는 한 inner join으로 left join을 섞지 마십시오. 테이블을 참조하는 별칭을 사용하여 on절을 작성합니다.

GOOD:

SELECT *
  FROM Production.Product AS prd
  JOIN Production.ProductModel AS prm
    ON prd.ProductModelID = prm.ProductModelID
  LEFT JOIN Production.ProductSubcategory AS psc
    ON prd.ProductSubcategoryID = psc.ProductSubcategoryID
  LEFT JOIN Production.ProductDocument AS doc
    ON prd.ProductID = doc.ProductID

BAD:

SELECT *
  FROM Production.Product AS prd
  LEFT JOIN Production.ProductSubcategory AS psc
    ON psc.ProductSubcategoryID = prd.ProductSubcategoryID  -- backwards
  JOIN Production.ProductModel AS prm                       -- intermingled
    ON prm.ProductModelID = prd.ProductModelID              -- backwards
  LEFT JOIN Production.ProductDocument AS doc
    ON prd.ProductID = doc.ProductID

보통 left join으로 더 잘 쓰므로, right join을 피하십시오.

GOOD:

SELECT *
  FROM Production.Product AS prd
  LEFT JOIN Production.ProductSubcategory AS psc
    ON ...

BAD:

SELECT *
  FROM Production.ProductSubcategory AS psc
 RIGHT JOIN Production.Product AS prd
    ON ...

where clause

여러 개의 where 절은 서로 다른 선으로 이동하여 river에 정렬해야 합니다.

SELECT *
  FROM Production.Product AS prd
 WHERE prd.Weight > 2.5
   AND prd.ListPrice < 1500.00
   AND Color IN ('Blue', 'Black', 'Red')
   AND SellStartDate >= '2006-01-01'
...

andor을 혼합하는 경우 작업 순서에 의존하지 말고 항상 괄호를 사용하도록 합니다.

SELECT *
  FROM Production.Product AS prd
 WHERE (prd.Weight > 10.0
   AND Color IN ('Red', 'Silver'))
    OR Color IS NULL

세미콜론을 사용할 때는 항상 다음 줄에 세미콜론을 놓으십시오. 이렇게 하면 여기서 절에 조건을 추가하고 후행 세미콜론 이동을 무시하는 것과 같은 일반적인 오류를 방지할 수 있습니다.

GOOD:

-- The prefix semicolon is clear and easy to spot when adding to a `where`
DELETE prd
  FROM Production.Product AS prd
 WHERE prd.ListPrice = 0
   AND weight IS NULL
   AND size IS NULL
;
...

BAD:

-- A trailing semicolon is sinister.
-- We added some where conditions and missed it.
-- This is a destructive bug.
DELETE prd
  FROM Production.Product prd
 WHERE prd.ListPrice = 0;  -- dangerous
   AND weight IS NULL      -- syntax error here, but the bad delete is valid
   AND size IS NULL
...

group by clause

group byselect와 동일한 순서로 사용합니다.

GOOD:

  SELECT poh.EmployeeID
       , poh.VendorID
       , COUNT(*) AS OrderCount
       , AVG(poh.SubTotal) AS AvgSubTotal
    FROM Purchasing.PurchaseOrderHeader AS poh
GROUP BY poh.EmployeeID
       , poh.VendorID

BAD:

  SELECT poh.EmployeeID
       , poh.VendorID
       , COUNT(*) AS OrderCount
       , AVG(poh.SubTotal) AS AvgSubTotal
    FROM Purchasing.PurchaseOrderHeader AS poh
GROUP BY poh.VendorID	-- out of order
       , poh.EmployeeID

having clause

having 절은 집합 함수에 대한 where 절일 뿐입니다. where절과 동일한 룰을 적용합니다.

Example:

  SELECT poh.EmployeeID
       , poh.VendorID
       , COUNT(*) AS OrderCount
       , AVG(poh.SubTotal) AS AvgSubTotal
    FROM Purchasing.PurchaseOrderHeader AS poh
GROUP BY poh.EmployeeID
       , poh.VendorID
  HAVING COUNT(*) > 1
     AND AVG(poh.SubTotal) > 3000.00

order by clause

order by 구문에서 불필요한 asc를 사용하지 않습니다.

GOOD:

-- asc is implied and obvious
  SELECT per.LastName
       , per.FirstName
    FROM Person.Person AS per
ORDER BY per.LastName
       , per.FirstName

BAD:

-- asc is clutter - it's never ambiguous when you wanted to sort ascending
  SELECT per.LastName
       , per.FirstName
    FROM Person.Person AS per
ORDER BY per.LastName ASC	-- useless asc
       , per.FirstName ASC

컬럼 번호로 정렬하는 것은 괜찮지만, 선호하지 않습니다.

-- This is okay, but not great.
  SELECT per.FirstName + ' ' + per.LastName AS FullName
       , per.LastName + ', ' + per.FirstName AS LastFirst
    FROM Person.Person AS per
ORDER BY  

by키워드는 7번째 컬럼에 올 수 있지만 컬럼 이름별로 정렬을 해야합니다.

SELECT per.FirstName
     , per.LastName
  FROM Person.Person AS per
 ORDER BY per.LastName
        , per.FirstName

세 개 이하의 열이 order by이고 짧은 이름이 있는 경우 간략하게 동일한 줄에 포함되도록 선택할 수 있습니다.

-- shortcut for small columns
SELECT per.FirstName, per.LastName
  FROM Person.Person AS per
 ORDER BY per.LastName, per.FirstName

 

반응형
댓글