2010-07-21 78 views
1

我有一個Access數據庫,其中包含一個表格,其中包含有關我們排序的部分的信息。該表具有自動編號ID字段和110ID,該110ID通過零件信息鏈接到另一個表。它還包含一個sortDate,sortShift,排序,報廢和修復。我需要找出自從最後一個缺陷(沒有報廢或修復)被發現的每個110ID以來有多少部分已經被排序。爲每個組選擇top 1

問題是我不能保證信息將按時間順序輸入到數據庫中。所以我需要爲'sortDate'大於最後一個缺陷,或者'sortDate'與最後一個缺陷相同但是'sortShift'更大的任何記錄求和'sorted'字段,或者使用自動編號作爲最後的手段如果'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是Access標準之一,那麼你可能需要調整它們。

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)OR(SI2.Scrapped <> 0))AND。 ..'但它似乎並不會允許extra()將兩個or'd語句分組。選項二似乎不起作用,或者它同樣緩慢。 – AdmSteck 2010-07-21 19:30:02

+0

這是非常奇怪的,它不允許括號。不幸的是,我沒有在這臺PC上進行測試。你確定某個地方沒有錯別字嗎? – 2010-07-21 19:35:31

+0

Access/Jet/ACE對其JOIN語法非常挑剔。還要注意,NOT IN和NOT EXISTS通常沒有被Jet很好地優化,並且可能僅在比較的一側使用索引。 – 2010-07-22 19:16:33