2011-07-07 52 views
1

我們最近有一些問題,從表中刪除重複條目的sql腳本不會使用最新的條目作爲保留的條目。我認爲,這條線是問題奇怪的刪除查詢,它寫的是否正確?

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
    from vaccine_patient_details as v 
    where v.patient_guid = patient_guid and 
      v.vaccine_guid = vaccine_guid 
    order by date_given desc) 

那是正確的語法?我發現另一個版本的腳本在不同的表格上工作。 (名稱變更爲第一個例子匹配)

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
    from vaccine_patient_details as v 
    where v.patient_guid = vaccine_patient_details.patient_guid and 
      v.vaccine_guid = vaccine_patient_details.vaccine_guid 
    order by date_given desc) 

這其中使用了已刪除的表的表名內where子句中,可以說是導致在我的第一個版本的問題嗎?有關表

詳細說明:

  1. 在GUID結束的任何列是唯一標識符
  2. vacc_pat_guid的 數據類型是主鍵而且是唯一的。
  3. date_given是可以爲空的日期時間。如果有一個重複的地方,其中一個是空的,而另一個不是空的,它應該更喜歡不是空的那個。

回答

3

內部消除在第一個表的別名,查詢等效於:

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
    from vaccine_patient_details as v 
    where v.patient_guid = v.patient_guid and 
      v.vaccine_guid = v.vaccine_guid 
    order by date_given desc) 

和良好的人會

delete v1 from vaccine_patient_details as v1 
where v1.vacc_pat_guid <> 
    (Select top 1 v.vacc_pat_guid 
    from vaccine_patient_details as v 
    where v.patient_guid = v1.patient_guid and 
      v.vaccine_guid = v1.vaccine_guid 
    order by v.date_given desc) 

通過在第二個查詢specifiying表名你向我們顯示,優化者明白他必須加入第一張表,因爲第二張表被命名爲'v',而第一張是'vaccine_patient_details',他不會混淆。

他第一次感到困惑,因爲他不知道patient_guid是第一張表還是第二張表中的字段。所以它接近了,所以第二個。

編輯:

http://dev.mysql.com/doc/refman/5.0/en/delete.html

如果你聲明的別名爲表, 你指 表時,必須使用別名:

DELETE t1 FROM test AS t1, test2 WHERE ...

+0

您不能在刪除語句中使用別名。它給出錯誤'Msg 102,Level 15,State 1,Line 1 'v1'附近的語法不正確。' –

+0

不過,我認爲你是正確的第一部分,它是比較錯誤的表。我只是有人可以給予確認而不是「我想」。 –

+0

'Msg 156,Level 15,State 1,Line 1 關鍵字'as'附近的語法不正確。' –

1

無論是lega l或不與同一張桌子連接,這不是一個好主意。您最好將您認爲應該刪除的記錄的id提取到單獨的表格中(然後您可以驗證它們是否正確),然後使用它們運行刪除。

我想嘗試刪除基於這樣的複雜查詢是在某些時候要求麻煩。

+0

+1用於提取ID。斯科特,你可能想用這些來審計刪除,因爲刪除的行不是真正重複的。 –

+0

你能否提供一個如何獲取最新記錄並將其提取到臨時表中的示例(我知道如何執行提取部分,但是我在正確的select語句中遇到了一些問題) –

0

這給一個嘗試(在你的開發環境,當然)

delete vaccine_patient_details 
    from vaccine_patient_details V 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
     from vaccine_patient_details 
     where V.patient_guid = patient_guid and 
      V.vaccine_guid = vaccine_guid 
     order by date_given desc) 
1

你的代碼的相關部分是(正如你指出)這個...

where v.patient_guid = patient_guid and 
     v.vaccine_guid = vaccine_guid 

等號運算符的右側沒有指定表。優化器將首先檢查最匹配的表的本地範圍。在這種情況下,子查詢中的表具有這些字段,優化後甚至不檢查外部查詢中的表。

代碼的第二個版本明確指出要引用哪個表,這恰好是外部查詢中的表。

所以,總之,是的;問題在於第一個版本隱式引用表的內部查詢的實例,並且它應該明確引用外部查詢的表的實例。

注:我不同意這種自連接是一個問題。

1
delete a from vaccine_patient_details a, vaccine_patient_details b 
where a.patient_guid = b.patient_guid 
    and a.vaccine_guid = b.vaccine_guid 
    and a.date_given < b.date_given