2012-12-06 110 views
1

我需要編寫SQL,只保留表中每個可識別記錄的最少5條記錄。爲此,我使用partition by並刪除返回值大於5的所有記錄。當我嘗試在與partition by語句相同的查詢中使用WHERE子句時,出現錯誤「在WHERE子句中不允許的有序分析函數」 。所以,爲了使它起作用,我必須使用三個子查詢。我的SQL看起來像這樣:是否可以在與PARTITION BY相同的查詢中使用WHERE子句?

delete mydb.mytable where (field1,field2) in 
(
    select field1,field2 from 
    (
     select field1,field2, 
     Rank() over 
     (
      partition BY field1 
      order by field1,field2 
     ) n 
     from mydb.mytable 
    ) x 
    where n > 5 
) 

最內層的子查詢只是返回原始數據。由於我不能在那裏使用WHERE,我用子查詢包裝它,其目的是1)使用WHERE獲得大於5的記錄,2)僅選擇field1和field2。我只選擇這兩個字段的原因是,我可以使用IN語句刪除最外層查詢中的這些記錄。

它可以工作,但看起來有點麻煩。我想將內部的兩個子查詢合併成一個子查詢。這可能嗎?

+0

不能直接評論你的問題,但我認爲你應該考慮使用'ROW_NUMBER()'而不是'RANK()',萬一有任何「關係」。 – BellevueBob

+0

我會查看row_number。不過,不會有任何關係,因爲比較僅在唯一索引上完成。 – oscilatingcretin

回答

0

聽起來像你需要使用QUALIFY子句,它是窗口聚合函數的HAVING子句。以下是我對你想要完成的事情的看法。

請不要直接對您的生產數據運行此SQL,而無需先進行測試。

/* Physical Delete */ 
DELETE TGT 
    FROM MyDB.MyTable TGT 
INNER JOIN 
     (SELECT Field1 
      , Field2 
     FROM MyDB.MyTable 
     QUALIFY ROW_NUMBER() (PARTITION BY Field1, ORDER BY Field1,2) 
       > 5 
     ) SRC 
    ON TGT.Field1 = SRC.Field1 
    AND TGT.Field2 = SRC.Fileld2 

/* Logical Delete */ 
UPDATE TGT 
    FROM MyDB.MyTable TGT 
    , 
     (SELECT Field1 
      , Field2 
     FROM MyDB.MyTable 
     QUALIFY ROW_NUMBER() (PARTITION BY Field1, ORDER BY Field1,2) 
       > 5 
     ) SRC 
    SET Deleted = 'Y' 
    /* RecordExpireDate = Date - 1 */ 
WHERE TGT.Field1 = SRC.Field1 
    AND TGT.Field2 = SRC.Fileld2 
相關問題