하나의 테이블에 존재하지 않는 행이있는 행을 표시하는 SQL 조인 쿼리


12

직원 시간 기록에 대한 보고서를 작성하려고합니다.

이 질문에 특별히 두 개의 테이블이 있습니다. 직원은 Members테이블에 나열되며 매일 수행 한 작업 시간 항목을 입력하고 Time_Entry테이블에 저장됩니다 .

SQL Fiddle을 사용한 설정 예 : http://sqlfiddle.com/#!3/e3806/7

내가 갈거야 최종 결과는 쇼 테이블입니다 ALLMembers 열 목록에서 다음이 다른 컬럼에 조회 날짜에 대한 자신의 합계 시간을 표시합니다.

문제 Time_Entry는 특정 멤버 의 테이블에 행이없는 경우 해당 멤버에 대한 행이있는 것 같습니다. 여러 가지 조인 유형 (Left, Right, Inner, Outer, Full Outer 등)을 시도했지만 원하는 것을 제공하지 않는 것 같습니다 (SQL Fiddle의 마지막 예를 기반으로 함).

/*** Desired End Result ***/

Member_ID   | COUNTTime_Entry | TIMEENTRYDATE | SUMHOURS_ACTUAL | SUMHOURS_BILL
ADavis      | 0               | 11-10-2013    | 0               | 0
BTronton    | 0               | 11-10-2013    | 0               | 0
CJones      | 0               | 11-10-2013    | 0               | 0
DSmith      | 0               | 11-10-2013    | 0               | 0
EGirsch     | 1               | 11-10-2013    | 0.92            | 1
FRowden     | 0               | 11-10-2013    | 0               | 0

11-1의 특정 날짜를 쿼리 할 때 현재 얻고있는 것 :

Member_ID   | COUNTTime_Entry | TIMEENTRYDATE | SUMHOURS_ACTUAL | SUMHOURS_BILL
EGirsch     | 1               | 11-10-2013    | 0.92            | 1

EGirsch에 대해 날짜가 2013 년 11 월 10 일자 인 1 개의 시간 항목 행을 기준으로 올바른 것이지만이 정보에 대한 보고서와 웹 대시 보드 / 보고서를 얻으려면 다른 구성원에 대해 0이 필요합니다.

이것은 나의 첫 번째 질문이며, Join 쿼리 등을 검색하는 동안이 함수가 무엇을 호출하는지 잘 모르겠습니다. 이것은 중복되지 않으며 다른 사람들도 해결책을 찾는 것을 도울 수 있기를 바랍니다. 비슷한 문제.

답변:


11

SQLfiddle 및 샘플 데이터에 감사드립니다! 더 많은 질문이 이런 식으로 시작되기를 바랍니다.

해당 날짜에 대한 항목이 있는지 여부에 관계없이 모든 구성원을 원하면을 원합니다 LEFT OUTER JOIN. 이 버전에 매우 가까웠 지만 외부 조인의 약간의 트릭은 WHERE절의 외부 테이블에 필터를 추가 하면 외부 조인을 내부 조인으로 NULL설정한다는 것입니다. ( NULL필터와 일치 하는지 여부를 알 수 없기 때문에 ).

모든 멤버에 대한 행을 얻도록 첫 번째 쿼리를 수정했습니다.

SELECT Members.Member_ID
      ,Time_Entry.Date_Start
      ,Time_Entry.Hours_Actual
      ,Time_Entry.Hours_Bill
FROM dbo.Members
  LEFT OUTER JOIN dbo.Time_Entry
--^^^^ changed from FULL to LEFT
  ON Members.Member_ID = Time_Entry.Member_ID
  AND Time_Entry.Date_Start = '20131110';
--^^^ changed from WHERE to AND

독자가 거기에서 가져 와서 다른 열, 서식 COALESCE등을 추가하는 연습으로 남겨 두겠습니다 .

다른 참고 사항 :


애런, 피드백 주셔서 대단히 감사합니다. SQL 여기에 초보자, 그리고 아무 생각의 차이 없었다 WHEREAND. 나는 원래 별명을 사용했지만 sqlfiddle은 그것을 좋아하지 않는 것처럼 보이므로 전체 형식으로 갔다. 다른 SQL 팁도 감사합니다. 당신은 권하고 싶습니다 ISNULL또는 COALESCE데이터를 만들기 위해 공을 대신 NULL? 다시 감사합니다!
farewelldave 14

1
@farewelldave COALESCE는 표준이며 다른 언어의 기능에서 벗어나지 않기 때문에 선호합니다 (예 : SQL Server와 VB에서 ISNULL의 작동 방식 비교). 거의 모든 경우에서 성능 차이는 중요하지 않습니다 (하나를 제외하고). 자세한 내용은 여기를 참조하십시오 .
Aaron Bertrand

4

과거에 이런 유형의 문제에 직면했을 때 누락 된 행을 처리하는 데 도움이 되는 "숫자" 테이블을 만들었습니다 .

날짜를 처리하기 위해 특별히 숫자 테이블을 만들었습니다.

CREATE TABLE Dates
(
    dDate DATETIME NOT NULL CONSTRAINT PK_Dates PRIMARY KEY CLUSTERED
);

INSERT INTO Dates (dDate)
SELECT TOP(73049) DATEADD(d, -1, ROW_NUMBER() OVER (ORDER BY o.object_id)) AS dDate
FROM master.sys.objects o, master.sys.objects o1, master.sys.objects o2

이렇게하면 1900-01-01과 2099-12-31 사이의 각 날짜마다 단일 행이있는 테이블이 작성됩니다. TOP(73049)예제에서 생성 된 날짜 범위를 날짜로 제한하는 데 사용 합니다. 다른 날짜 범위로 작업하는 경우 해당 숫자를 조정할 수 있습니다.

다음으로 dDates쿼리에 테이블을 추가하여 모든 날짜마다 원하는 범위의 행이 반환되도록합니다 member_id. 결과는 다음 Time_Entry과 같이 테이블에 결합됩니다 .

SELECT MD.Member_ID,
    MD.dDate,
    T.Date_Start,
    T.Hours_Actual,
    T.Hours_Bill
FROM 
    (
        SELECT M.Member_ID, D.dDate
        FROM dbo.Dates D, dbo.Members M
        WHERE D.dDate >= '20131110' AND D.dDate < '20131112'
    ) AS MD
    LEFT JOIN dbo.Time_Entry T ON MD.Member_ID = T.Member_ID AND MD.dDate = T.Date_Start
ORDER BY MD.Member_ID, MD.dDate

보고서의 날짜 범위를 지정할 수 있습니다.

다음 COALESCE(...)SUM(...)같이 추가하여 결과를 더 세분화 할 수 있습니다 .

SELECT MD.Member_ID,
    MD.dDate,
    T.Date_Start,
    SUM(COALESCE(T.Hours_Actual, 0)) AS TotalHoursActual,
    SUM(COALESCE(T.Hours_Bill, 0)) AS TotalHoursBill
FROM 
    (
        SELECT M.Member_ID, D.dDate
        FROM dbo.Dates D, dbo.Members M
        WHERE D.dDate >= '20131110' AND D.dDate < '20131112'
    ) AS MD
    LEFT JOIN dbo.Time_Entry T ON MD.Member_ID = T.Member_ID AND MD.dDate = T.Date_Start
GROUP BY MD.Member_ID, MD.dDate, T.Date_Start
ORDER BY MD.Member_ID, MD.dDate

그 결과 샘플 데이터에 대해 다음과 같은 결과가 나타납니다.

여기에 이미지 설명을 입력하십시오


고마워, 맥스 "numbers table"대신 "tally table"을 검색하여이 기술에 대한 많은 정보를 찾을 수 있습니다. 커서 / 루프를 사용하는 작업을 세트를 사용하는 작업으로 변환하여 성능을 향상시키는 데 유용합니다. 관계형 데이터베이스는 세트를 선호합니다.
Suncat2000

1
@ Suncat2000-동의합니다. 집계에 추가가 필요하기 때문에 "숫자 테이블"이라는 이름을 선호하지만 내 경험상이 패턴은 수학 연산에 거의 사용되지 않습니다. 그것들은 많은 것들에 훌륭하지만, 당신이 얻을 수있는 가장 큰 성능 개선 중 하나는 숫자 테이블을 사용하여 RBAR 접근법에서 세트 기반 접근법으로가는 것입니다.
Max Vernon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.