복잡한 SQL 쿼리를보다 쉽게 ​​작성하려면 어떻게해야합니까? [닫은]


42

많은 (최소 3-4) 테이블에서 조인과 여러 중첩 조건이 관련된 복잡한 SQL 쿼리를 작성하는 것이 매우 어렵다는 것을 알고 있습니다. 내가 작성하도록 요청받은 쿼리는 몇 문장으로 쉽게 설명 할 수 있지만기만적인 코드가 필요할 수 있습니다. 나는 종종 임시 견해를 사용하여 이러한 쿼리를 작성하는 것을 발견하고 있는데, 이는 약간의 목발처럼 보입니다. 복잡한 쿼리를보다 쉽게하기 위해 사용할 수있는 팁은 무엇입니까? 보다 구체적으로, 이러한 쿼리를 실제로 SQL 코드를 작성하는 데 사용해야하는 단계로 나누려면 어떻게해야합니까?

내가 작성하도록 요청받은 SQL은 데이터베이스 코스에 대한 과제 할당의 일부이므로 나에게 도움이되는 소프트웨어는 원하지 않는다. 실제로 작성한 코드를 이해하고 싶습니다.

더 많은 기술적 세부 사항 :

  • 데이터베이스는 로컬 컴퓨터에서 실행되는 PostgreSQL 서버에서 호스팅됩니다.
  • 데이터베이스는 매우 작습니다. 테이블이 7 개 이하이고 가장 큰 테이블의 행이 약 50 개 미만입니다.
  • SQL 쿼리는 LibreOffice Base를 통해 변경없이 서버로 전달됩니다.

임시 뷰는 SQL 파서에 암시하기 매우 어려운 테이블 (예 : 명시 적 복합 인덱스)에 대한 작업을 수행 할 수 있으므로 실제로 매우 유용합니다.

개인적으로 GUI (예 : LibreOffice Base "디자인 쿼리에서 쿼리 만들기"또는 Office Access "Create"> "쿼리 디자인")를 사용하여 부정 행위를하는 것이 더 쉽다는 것을 알게되었습니다. 때로는 GUI 디자이너에 의해 주어진 SQL을 수정해야하지만 시작점 좋은를 제공합니다
kurdtpage

답변:


49

나는 "올바른"답변을 얻으려고 노력하면서 이것의 대부분을 기반으로하고 있으므로 성능 문제가 있음을 알 수 있습니다. 잘못된 쿼리 속도를 높일 필요가 없습니다.

테이블 관계 이해 -대부분 일대 다입니다. "많은"테이블을 알고 있습니다. 조인에 필요한 필드를 식별하십시오.

LEFT 가입 시나리오를 고려하십시오 -지난 달의 모든 직원과 월급을 선택하십시오. 지난 달에 급여를받지 못하면 어떻게됩니까?

결과 집합을 파악하십시오. 1) 스프레드 시트에서 쿼리에 대한 올바른 레코드를 하나 이상 수동으로 입력하십시오. 2) 얼마나 많은 레코드를 반환해야하는지 식별 할 수있는 간단한 형태로 쿼리를 작성하십시오. 이 두 가지를 모두 사용하여 새 테이블을 조인해도 결과가 변경되지 않도록 쿼리를 테스트하십시오.

쿼리를 다루기 쉬운 부분으로 나눕니다 . 한 번에 모두 쓸 필요는 없습니다. 복잡한 쿼리는 간단한 쿼리 모음 일 수 있습니다.

혼합 수준의 집계주의 : 월별, 분기 별 및 연도 별 값을 동일한 결과 집합에 넣어야하는 경우 서로 다른 값으로 그룹화 된 쿼리에서 별도로 계산해야합니다.

UNION시기를 알기 때때로 하위 그룹을 자체 select 문으로 나누는 것이 더 쉽습니다. 관리자와 다른 직원이 혼합 된 테이블이 있고 각 열에 이러한 그룹 중 하나의 구성원 자격을 기반으로 사례를 작성해야하는 경우 관리자 쿼리와 통합 쿼리를 직원 쿼리에 작성하는 것이 더 쉬울 수 있습니다. 각각에는 자체 논리가 포함됩니다. 다른 테이블의 항목을 다른 행에 포함시키는 것이 명백한 용도입니다.

복잡하고 중첩 된 공식 -일관되게 들여 쓰기를하고 여러 줄을 사용하는 것을 두려워하지 마십시오. "Case WHEN CASE WHEN CASE WHEN"은 견과류를 운전합니다. 이것을 생각할 시간을 가지십시오. 마지막으로 복잡한 계산을 저장하십시오. 먼저 올바른 레코드를 선택하십시오. 그런 다음 올바른 값으로 작업하고 있다는 것을 알고 복잡한 수식을 공격합니다. 수식에 사용 된 값을 보면 NULL 값을 설명해야하는 영역과 0으로 나누기 오류를 처리 할 위치를 찾는 데 도움이됩니다.

새 테이블을 추가 할 때 자주 테스트하여 원하는 결과 집합을 얻고 있고 어떤 조인 또는 절이 원인인지 확인하십시오.


1
정말 훌륭한 것들. LEFT 조인을 찾고 복잡한 쿼리를보다 작고 관리하기 쉬운 쿼리로 분할 한 다음 결합하는 것에 대한 Jeff의 요점을 다시 강조하고 싶습니다. 나는 거의 매일 큰 데이터베이스에 큰 쿼리를 작성하고 특히 그 두 가지가 항상 나타납니다. 각 단계에서 예상되는 데이터를 얻을 수 있도록 가능한 빨리 쿼리와 하위 쿼리를 실행하십시오.
CodexArcanum

@CodexArcanum-빅 데이터에 대한 쿼리를 실행할 때 TOP을 사용해도 문제가되지 않습니다.)
JeffO

귀하의 제안에 대한 모든 진술에 동의합니다
Alessandro Rossi

28
  1. 들여 쓰기 는 아직 수행하지 않은 경우 가장 먼저 수행해야합니다. 간단한 쿼리조차도 유용 할뿐만 아니라 a보다 좀 더 복잡한 조인 및 쿼리와 관련하여 매우 중요합니다 select top 1 [ColumnName] from [TableName].

  2. 제대로 들여 쓰기되면 , 적절한 경우 쿼리 자체 내에 주석추가 할 수 없습니다. 코드를 과도하게 사용하지 마십시오. 코드가 충분히 명시 적이면 주석을 추가하면 코드의 선명도가 떨어집니다. 그러나 그들은 여전히 ​​덜 명확한 쿼리 부분에 대해 환영합니다.

    쿼리가 길면 (댓글이있는 쿼리 포함) 응용 프로그램 서버와 데이터베이스 서버 간의 대역폭 사용량이 더 커집니다. 또한 초당 엄청난 양의 요청으로 뛰어난 성능과 리소스 사용이 필요한 Google 규모의 제품을 작업하지 않는 한 의견에 의해 추가 된 크기는 성능 측면에서 아무런 변화를주지 않을 수 있습니다.

  3. 테이블, 열 등에 동일한 스타일을 적용하면 가독성도 크게 향상됩니다. 기존 데이터베이스 테이블이있는 경우 PRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSHRhbYd_UU, 사람은 매우 잘못된 일을하고있다.

  4. 쿼리에 동일한 스타일을 적용하는 것도 중요합니다. 예를 들어 Microsoft SQL Server에 대한 쿼리를 작성하고 [TableName]대신 대신 사용하기로 결정한 경우 계속 사용 TableName하십시오. 의 다음에 새 줄로 가면 select쿼리의 절반 만 수행하지 말고 모든 쿼리를 수행하십시오.

  5. *if exists(select * from [TableName] where ...)Microsoft SQL Server에서 와 같이 강력한 이유가 없는 한을 사용하지 마십시오 . 뿐만 아니라 *부정적인 성능의 일부에 미치는 영향 (그렇지 않으면 대부분의) 데이터베이스를 가지고 있지만, 그것은 또한 당신의 쿼리를 사용하는 개발자에게 도움이되지이다. 같은 방식으로 개발자는 색인이 아닌 이름으로 값에 액세스해야합니다.

  6. 마지막으로, 선택의 경우 보기 를 제공하는 데 아무런 문제가 없습니다 . 다른 작업의 경우 프로젝트 및 작업중인 사람 ¹에 따라 저장 프로 시저를 사용할 수도 있습니다.


¹ 일부 사람들은 저장 프로 시저를 싫어합니다. 다른 사람들은 여러 가지 이유로 (적어도 적어도 유효한) 이유를 좋아하지 않습니다.

² 동료, 다른 학생, 교사 등


9

여기서 약간의 기회를 얻었지만 임시 뷰를 많이 작성하는 경우 SQL 문에 테이블을 넣을 수있는 대부분의 장소를 아직 알지 못했을 것입니다. 테이블은 쿼리로 대체 될 수 있습니다.

따라서 테이블 A를 임시 뷰 B에 조인하는 대신 테이블 A를 임시 뷰 B로 사용한 쿼리에 조인 할 수 있습니다. 예를 들면 다음과 같습니다.

    SELECT A.Col1, A.Col2, B.Col1,B.Col2
      FROM (SELECT RealTableZ.Col1, RealTableY.Col2, RealTableY.ID as ID
              FROM RealTableZ 
   LEFT OUTER JOIN RealTableY
                ON RealTableZ.ForeignKeyY=RealTableY.ID
             WHERE RealTableY.Col11>14
            ) As B
        INNER JOIN A
                ON A.ForeignKeyY=B.ID

이 예제는 다소 의미가 없지만 구문을 설명해야합니다.

"특별한"(인덱싱, 파티션 된) 뷰가 아닌 경우 뷰를 사용한 것과 동일한 쿼리 계획이 있어야합니다.

보다 쉽게 ​​작성할 수있는 한, 각 조각을 확인하여 전체 쿼리를 작성하기 전에 원하는 내용을 얻을 수 있습니다.

이것이 이미 당신에게 낡은 모자 인 경우에 사과드립니다.


3
나는 SQL에 대해 꽤 전문가이고 나는이 들여 쓰기를 정말로 싫어한다. 멋져 보일지 모르지만 "내 의견으로는"완전히 쓸모가 없다. 두 가지 이유 : 왼쪽 외부 조인이 기본 쿼리의 일부인지 하위 쿼리의 일부인지 명확하게 이해할 수 없으므로 코드 미용사가 필요하며 몇 줄을 추가 할 때마다 모든 텍스트를 다시 아름답게해야합니다. . TABS 만 필요한 계획 들여 쓰기는 훨씬 유연합니다. 나는 당신의 대답을 다운 투표하지 않았지만이 스타일을 사용하는 사람을 특히 실망시킵니다 ... 특히 그들이 내 도움이 필요할 때.
Alessandro Rossi

7

임시 뷰 대신 WITH 절을 사용하십시오 . 따라서 큰 쿼리를 더 읽기 쉬운 작은 부분으로 나누기가 훨씬 쉽습니다.


1
cte를 사용하는 경우 다음 쿼리가 실행될 때까지만 쿼리가 유지되므로 여러 쿼리에서 cte를 사용하는 경우 임시 테이블을 사용하는 것이 더 좋습니다.
Rachel

3
  1. 아직 설정 이론에 익숙해지지 마십시오. SQL은 집합 이론을 기반으로하며 집합에 대한 자세한 내용을 이해하면 SQL 작동 방식을보다 잘 이해할 수 있습니다.
  2. 더 많은 SQ1을 연습하십시오 .SQL을 배우는 경우 모든 것을 수행하는 방법을 이해하는 데 시간이 걸리고 실제로 이해하기 전에 시간이 걸리는 경우 조인은 더 잘 사용할수록 더 좋은 예입니다.
  3. 쿼리하는 테이블이 올바르게 설계되었는지 확인하십시오.
  4. 선택 쿼리에서 뷰를 사용하는 것을 두려워하지 마십시오. 특히 여러 가지 다른 방법으로 세분화해야하는 공통 세트가있는 경우

1

다른 것과 마찬가지로 문제를 관리 가능한 부분으로 나누고 싶습니다.

그건 그렇고 복잡한 문제를 해결하는 방법입니다.

따라서 외부 쿼리를 실행하기 전에 하위 쿼리를 확인하여 실제로 원하는 것을 반환하는지 확인하려고합니다. 조인하는 각 테이블의 최소 조인을 시도하여 제대로 생각하고 있음을 알 수 있습니다. 그런 것들. 모든 것을 입력하고 한 번에 원하는 것을 정확하게 얻으려는 것은 비현실적입니다.

SQL 문은 특정 수준의 복잡성에 도달하면 기본적으로 자체적으로 작은 프로그램입니다. 데이터의 결합, 선택, 필터링 및 출력 방법을 실제로 이해하는 데 큰 차이가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.