2013-05-10 175 views
2

我正在使用PHP和MySQL。 任何人都可以告訴我一個有效的方法來篩選出基於優先級的重複結果嗎?基於列優先級的SQL篩選器重複項

實施例:

我有一個表:

ID | Priority 1 | Priority 2 | Priority 3 | E-Mail 
-------------------------------------------------------------- 
1 | Apple  | One   | Low   | [email protected] 
2 | Banana  | Two   | Medium  | [email protected] 
3 | Banana  | Two   | High  | [email protected] 
4 | Banana  | Two   | High  | [email protected] 
5 | Peach  | Three  | Low   | [email protected] 
6 | Peach  | Four  | High  | [email protected] 

在上述例子中,我在尋找一種方法來只獲得行1,3(或4)和6
即就像第2,3,4行的電子郵件和5,6是相同的,它們是重複的記錄。我想根據優先級選擇記錄。
如果重複記錄的優先級1是相同的,我將轉到優先級2.如果這也是相同的,那麼我將轉到優先級3.如果相同,那麼選擇哪個並不重要。
但是,如果有差異,我選擇較高優先級的記錄。 在上面的例子中,優先級是

Peach -> Banana -> Apple 
Four -> Three -> Two -> One 
High -> Medium -> Low 

然後我將插入結果到不同的數據庫中。

到目前爲止,我有一個查詢來獲取非重複。我正在考慮處理重複的第二個查詢。
第一個查詢處理約20,000條記錄。第二個查詢將處理大約5,000條記錄。

但是,我不確定完成該操作的有效方法。

我非常感謝任何幫助。

謝謝。

編輯:錯字:希望行1,3/4和6(沒有1,2和6)

+0

爲什麼記錄2,具有中等優先級,而不是3或4? – fthiella 2013-05-10 19:23:34

+0

正常化任何人? – Strawberry 2013-05-13 22:49:08

回答

0

該查詢應該給你,你需要的結果:

SELECT 
    MIN(ID), 
    EMail, 
    MIN(Priority1), 
    MIN(Priority2), 
    MIN(Priority3) 
FROM 
    yourtable 
WHERE 
    (EMail, Priority1, Priority2, FIELD(Priority3, 'High', 'Medium', 'Low')) IN (
    SELECT 
     EMail, 
     MIN(Priority1), 
     MIN(Priority2), 
     MIN(FIELD(Priority3, 'High', 'Medium', 'Low')) MinP3 
    FROM 
     yourtable 
    WHERE 
     (EMail, Priority1, FIELD(Priority2, 'Four', 'Three', 'Two', 'One')) IN (
     SELECT 
      EMail, 
      MIN(Priority1), 
      MIN(FIELD(Priority2, 'Four', 'Three', 'Two', 'One')) MinP2 
     FROM 
      yourtable 
     WHERE 
      (EMail, FIELD(Priority1, 'Peach', 'Banana', 'Apple')) IN 
      (SELECT 
      EMail, MIN(FIELD(Priority1, 'Peach', 'Banana', 'Apple')) MinP1 
      FROM 
      yourtable 
      GROUP BY 
      EMail) 
     GROUP BY 
      EMail) 
    GROUP BY 
     EMail) 
GROUP BY 
    EMail 

(我返回第3行而不是2,但如果我正確理解你的問題,它應該是正確的)。請參閱小提琴here。我懷疑它不會很快。我仍然想知道是否有辦法讓它更快。

編輯

您可以嘗試以下查詢。它使用了一種不同的邏輯,但它也使用帶有某些列的Priorities表,它們應該比FIELD函數快得多,但是有很多連接可能會減慢查詢的速度。

CREATE TABLE Priorities (
    Num INT, 
    Des VARCHAR(10), 
    Priority INT, 
    PRIMARY KEY (Num, Des) 
); 

INSERT INTO Priorities VALUES 
(1, 'Peach', 1), 
(1, 'Banana', 2), 
(1, 'Apple', 3), 
(2, 'Four', 1), 
(2, 'Three', 2), 
(2, 'Two', 3), 
(2, 'One', 4), 
(3, 'High', 1), 
(3, 'Medium', 2), 
(3, 'Low', 3); 

SELECT MIN(ID), yourtable.Email, MIN(Priority1) Priority1, MIN(Priority2) Priority2, MIN(Priority3) Priority3 
FROM 
    yourtable 
    INNER JOIN Priorities p1 ON yourtable.Priority1=p1.Des AND p1.Num=1 
    INNER JOIN Priorities p2 ON yourtable.Priority2=p2.Des AND p2.Num=2 
    INNER JOIN Priorities p3 ON yourtable.Priority3=p3.Des AND p3.Num=3 
    INNER JOIN (
    SELECT s1.EMail, MIN(MinP1) M1, MIN(MinP2) M2, MIN(MinP3) M3 
    FROM (
     SELECT EMail, MIN(p1.Priority) MinP1 
     FROM  yourtable INNER JOIN Priorities p1 
       ON yourtable.Priority1 = p1.Des AND p1.Num = 1 
     GROUP BY EMail) s1 
    INNER JOIN (
     SELECT EMail, p1.Priority Pr1, MIN(p2.Priority) MinP2 
     FROM  yourtable INNER JOIN Priorities p1 
       ON yourtable.Priority1 = p1.Des AND p1.Num = 1 
       INNER JOIN Priorities p2 
       ON yourtable.Priority2 = p2.Des AND p2.Num = 2 
     GROUP BY EMail, p1.Priority) s2 
    ON s1.EMail=s2.EMail AND s1.MinP1=s2.Pr1 
    INNER JOIN (
     SELECT EMail, p1.Priority Pr1, p2.Priority Pr2, MIN(p3.Priority) MinP3 
     FROM  yourtable INNER JOIN Priorities p1 
       ON yourtable.Priority1 = p1.Des AND p1.Num = 1 
       INNER JOIN Priorities p2 
       ON yourtable.Priority2 = p2.Des AND p2.Num = 2 
       INNER JOIN Priorities p3 
       ON yourtable.Priority3 = p3.Des AND p3.Num = 3 
     GROUP BY EMail, p1.Priority, p2.Priority) s3 
    ON s1.Email=s3.Email AND s1.MinP1=s3.Pr1 AND s2.MinP2=s3.Pr2 
    GROUP BY 
    s1.EMail) s 
    ON yourtable.EMail=s.Email 
    AND p1.Priority=s.M1 
    AND p2.Priority=s.M2 
    AND p3.Priority=s.M3 
GROUP BY 
    yourtable.EMail 

請參閱小提琴here。如果它仍然太慢,我們可以嘗試使用我的第一個查詢與第二個支持表一樣。或者我們應該將查詢分爲兩部分。

+0

嗨,非常感謝你如此快速的迴應和你的時間。對此,我真的非常感激。是的,我想要第3行(不是2) - 感謝您的支持!這確實解決了這個問題,並且這比我現在的解決方案還要快(把結果放入一個數組然後過濾它)。但是,如果您能找到更快的解決方案,我將非常感激。再次謝謝你! – 2013-05-10 20:15:06

+0

嗨,我試着在超過20,000條記錄的實際數據庫上運行這個查詢,並且超時。約100條記錄需要5秒以上。雖然,我感謝您的幫助,但此解決方案無法在數據庫上運行。你還有其他建議嗎?也許我可以分開查詢 - 首先我得到非重複的,然後我得到重複的記錄,並過濾只是基於優先事項?謝謝! – 2013-05-13 13:59:16

+0

@CheekuJee查詢很好,我認爲,還有其他解決方案,但它們非常相似。我認爲問題在於FIELD()函數緩慢。你應該使用索引的一些額外的表,只是給我一些時間,我會更新我的答案 – fthiella 2013-05-13 21:20:16