2010-02-26 3 views
1

다음은 두 테이블의 innerjoin 내 select 문,이 SQL innerjoin에는 어떤 문제가 있습니까?

if not exists(select EmpId from SalaryDetails 
       where EmpId in (select Emp_Id 
           from Employee where [email protected])) 
begin 
    // some statements here 
end 
else 
begin 
    SELECT e.Emp_Id, e.Identity_No, e.Emp_Name, 
     case WHEN e.SalaryBasis=1 THEN 'Weekly' 
      ELSE 'Monthly' end as SalaryBasis,e.FixedSalary, 
     (SELECT TOP 1 RemainingAdvance 
     FROM SalaryDetails 
     ORDER BY CreatedDate DESC) as Advance 
    FROM Employee as e inner join Designation as d on e.Desig_Id=d.Desig_Id 
    INNER JOIN SalaryDetails as S on e.Emp_Id=S.EmpId 
End 

내 결과 창,

alt text http://img220.imageshack.us/img220/7774/resultpane.jpg

그리고 내 SalaryDetails 표를

alt text http://img28.imageshack.us/img28/770/salarydettable.jpg

EDIT입니다 :,내 출력 그래서,

16 CR14 Natarajan를 주간에게, 150.00 354.00
17 cr12333 Pandian 주간 122.00 0.00

+1

귀하의 산출물. 나는 그것을 이해할 수 없으며 기꺼이 할 수도 없다. –

+1

@ 리벤 (Lieven)은 같은 논평을하려고 한 것입니다. 그는 그가 Advance에 대해 354 점을 얻었지만 SalaryDetails에서 다른 가치를 지녔다고 추측했습니다. –

+0

당신은 맞지만 내부 조인과 아무 관련이 없습니다. –

답변

2

Designation에 대한 조인이 사용되지 않은 것처럼 보이며 맨 위에있는 IF 문에서 사용한 WHERE 절도 누락되었습니다. Andy가 지적한 것처럼 부속 쿼리를 조인으로 이동시킬 수도 있습니다. 이것에 대해 테스트 할 DB가 없다면 아마 정확하지 않을 것입니다. 보기에 하위 쿼리를 이동

SELECT e.Emp_Id, e.Identity_No, e.Emp_Name, 
    case WHEN e.SalaryBasis=1 
     THEN 'Weekly' 
     ELSE 'Monthly' end as SalaryBasis, 
    e.FixedSalary,S.RemainingAdvance as Advance 
FROM Employee as e 
    INNER JOIN (
    SELECT TOP 1 EmpId, RemainingAdvance 
    FROM SalaryDetails 
    ORDER BY CreatedDate DESC) as S on e.Emp_Id=S.EmpId 
WHERE [email protected] 

앤디의 제안은 좋은, 훨씬 더 쉽게 읽을 수와 DB가 큰 경우 아마 훨씬 더 효율적입니다.

편집 : 그는 가까이 내 출력 왔기 때문에 나는 제이의 답변을 편집

(SELECT sd.empid, 
       sd.remainingadvance, 
       ROW_NUMBER() OVER (PARTITION BY sd.empid ORDER BY sd.createddate DESC) AS rank 
      FROM SALARYDETAILS sd 
      JOIN EMPLOYEE e ON e.emp_id = sd.empid 
         AND e.desig_id = @CategoryId) s 
      WHERE s.rank = 1 

(ANSWER) ...

당신은 잘못이 무엇인지에 관해서는 우리에게 단서를 준 경우 도움이 될
+0

그냥 팁 제이, 당신의 TOP 1 하위 쿼리는 조인에서 EmpID 앞에 적용될 것입니다. 따라서 EmpID 16 및 17 인 SalaryDetails에 2 개의 레코드가 있고 CreatedDesc로 정렬 할 때 처음 16 개가 있고 조인의 e.Emp_Id가 17 인 경우에는 SELECT TOP 1 ... 쿼리와 일치해야합니다. 나는 전에이 실수에 빠졌습니다. 실제로 약 6 개월 후에 눈치 채지 못했습니다. 직원 ID 당 TOP 1을 얻으려면 RANK()를 사용해야합니다. –

+0

@ Jay13 그것은 나를 위해 일한다. .. 그러나 나는 단지 1 개의 열을 얻는다. ... 나의 카테고리 그것은 2 개의 empIds에게 '16,17'을 준다. –

3

당신은 어떤 직원 ID의 하위 쿼리 (SELECT TOP 1 RemainingAdvance FROM SalaryDetails ORDER BY CreatedDate DESC)를 필터링하지 않을 수 있어야합니다

SELECT를 사용하지 않고 FROM 절에 해당 테이블 식을 옮기고 직원 ID를 포함 시키려고 할 것입니다 (예 : , 그리고 그 표현에 참여하십시오.

SELECT 
    e.Emp_Id,e.Identity_No,e.Emp_Name,case WHEN e.SalaryBasis=1 THEN 'Weekly' ELSE 'Monthly' end as SalaryBasis,e.FixedSalary, 
    from Employee as e inner join Designation as d on e.Desig_Id=d.Desig_Id 
    inner join SalaryDetails as S on e.Emp_Id=S.EmpId 
    inner join 
    (SELECT EmpID, RemainingAdvance, RANK() OVER (PARTITION BY EmpID ORDER BY CreatedDate DESC) AS SalaryRank FROM SalaryDetails ORDER BY CreatedDate DESC) as Advance ON Advance.EmpID = e.Emp_ID AND Advance.SalaryRank = 1 

이것은 내 머리 꼭대기에있는 것이므로 제대로 돌아 가기 위해 약간의 조정이 필요할 수 있습니다. RANK() 함수의 사용에주의하십시오. TOP 1을 사용하면 전체 테이블의 첫 번째 레코드 만 얻게됩니다. 직원 ID 당 의 첫 번째 레코드는입니다.

만약 내가 그 표 표현식을 직원 ID를 가져 와서 첫 번째 RemainingAdvance 값을 반환하는보기 또는 스칼라 값 함수로 만들면 TOP 1을 사용하고 직원 ID를 필터링 할 수 있습니다.

+0

@Andy 내 존재하지 않는 진술을 보면 두 명의 직원 ID 16,17 –

+0

+1 사실 실제로 무엇이 잘못되었는지 모르는 것에 비추어 볼 때 나는 이것이 최고의 추측이라고 생각합니다. –

+0

@Andy는 답장에서 나에게보기를 편집 할 수 있습니까? –

관련 문제