2010-07-21 3 views
1

나는 우리가 정렬하는 부분에 대한 정보가있는 테이블을 포함하는 Access 데이터베이스를 가지고 있습니다. 이 테이블에는 자동 번호 ID 필드와 부품 정보가있는 다른 테이블로 연결되는 110ID가 있습니다. 또한 sortDate, sortShift, 정렬, 스크랩 및 복구가 포함됩니다. 각 110ID에 대해 마지막 결함 (폐기 또는 수리되지 않음)이 발견 된 이후에 얼마나 많은 부품이 정렬되었는지 확인해야합니다.각 그룹에 대해 상단 1 선택

문제는 정보가 데이터베이스에 시간 순서대로 입력된다는 것을 보장 할 수 없다는 것입니다. 그래서 마지막 결함보다 큰 'sortDate'또는 마지막 결함과 같은 'sortDate'이지만 더 큰 'sortShift'가있는 레코드에 대해서는 '정렬 된'필드를 합계해야합니다. 그렇지 않으면 마지막으로 자동 ID를 사용하십시오 'sortDate'와 'sortShift'가 일치하는 경우

SELECT SortInfo.[110ID], Sum(SortInfo.Sorted) AS SumOfSorted 
FROM SortInfo 
WHERE (
    ((SortInfo.sortdate)>(select top 1 dupe.sortdate from sortinfo as dupe where  (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc))) 
    OR (((SortInfo.sortdate)=(select top 1 dupe.sortdate from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
     AND ((SortInfo.sortshift)>(select top 1 dupe.sortshift from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc))) 
    OR (((SortInfo.sortdate)=(select top 1 dupe.sortdate from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
     AND ((SortInfo.sortshift)=(select top 1 dupe.sortshift from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
     AND ((SortInfo.ID)>(select top 1 dupe.id from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
) 
GROUP BY SortInfo.[110ID]; 

문제는이 매우 느린 것입니다 :

내가 현재 사용하고있는 쿼리입니다. 더 좋은 성능을 낼 수있는 더 좋은 방법이 있습니까?

답변

0

모든 하위 쿼리를 사용하는 대신 LEFT OUTER JOIN 또는 NOT EXISTS 하위 쿼리를 사용하여이 작업을 수행 할 수 있습니다. 나는 Access를 많이 사용하지 않으므로, Access가 ANSI 표준을 따르지 않는 영역 중 하나 인 경우이를 조정해야 할 수도 있습니다.

SELECT 
    SI.[110ID], 
    SUM(SI.Sorted) AS SumOfSorted 
FROM 
    SortInfo SI 
LEFT OUTER JOIN SortInfo SI2 ON 
    SI2.Repaired <> 0 AND 
    SI2.Scrapped <> 0 AND 
    (
     SI2.SortDate > SI.SortDate OR 
     (SI2.SortDate = SI.SortDate AND SI2.SortShift > SI.SortShift) OR 
     (SI2.SortDate = SI.SortDate AND SI2.SortShift = SI.SortShift AND SI2.ID > SI.ID) 
    ) 
WHERE 
    SI2.ID IS NULL 
GROUP BY 
    SI.[110ID] 

SELECT 
    SI.[110ID], 
    SUM(SI.Sorted) AS SumOfSorted 
FROM 
    SortInfo SI 
WHERE 
    NOT EXISTS 
    (
     SELECT * 
     FROM 
      SortInfo SI2 
     WHERE 
      SI2.Repaired <> 0 AND 
      SI2.Scrapped <> 0 AND 
      (
       SI2.SortDate > SI.SortDate OR 
       (SI2.SortDate = SI.SortDate AND SI2.SortShift > SI.SortShift) OR 
       (SI2.SortDate = SI.SortDate AND SI2.SortShift = SI.SortShift AND SI2.ID > SI.ID) 
      )  
    GROUP BY 
     SI.[110ID] 
    ) 
+0

초기 연구 결과 : 논리는'할 필요가 있기 때문에 나는이 일을 옵션 하나를 얻을 수 없다 ((SI2.Repaired <> 0) 또는 (SI2.Scrapped <> 0)) 및. ..'하지만 Access에서는 두 개의 or'd 문을 그룹화 할 수있는 extra()를 허용하지 않습니다. 옵션 2는 작동하지 않거나 느린 것입니다. – AdmSteck

+0

괄호를 사용할 수 없다는 것은 매우 이상합니다. 불행히도이 PC를 테스트 할 Access가 없습니다. 어딘가에 오타가 없다고 확신합니까? –

+0

Access/Jet/ACE는 JOIN 구문에 대해 매우 까다 롭습니다. 또한 NOT IN 및 NOT EXISTS는 Jet에서 잘 최적화되지 않았으며 비교의 한 쪽에서 만 인덱스를 사용할 수 있습니다. –

관련 문제