2016-10-26 48 views
3

我有這樣的查詢。我有CC.key1,CC.key2的複合索引。 我在一個大的數據庫在使用子查詢的表格中,如何有效地檢查記錄是否存在超過2次?

Select * from CC where 

( (
    (select count(*) from Service s 
      where CC.key1=s.sr2 and CC.key2=s.sr1) > 2 
    AND 
    CC.key3='new' 
    ) 
OR 
    (
    (select count(*) from Service s 
      where CC.key1=s.sr2 and CC.key2=s.sr1) <= 2 
    ) 
    ) 
limit 10000; 

我試圖使它的內部聯接執行這一點,但它的越來越慢。我怎樣才能優化這個查詢?

回答

0

基本上得到一定不能有重複的列,然後將它們連接在一起。例如:

select * 
FROM Table_X A 
WHERE exists (SELECT 1 
       FROM Table_X B 
       WHERE 1=1 
       and a.SHOULD_BE_UNIQUE = b.SHOULD_BE_UNIQUE 
       and a.SHOULD_BE_UNIQUE2 = b.SHOULD_BE_UNIQUE2 
       /* excluded because these columns are null or can be Duplicated*/ 
       --and a.GENERIC_COLUMN = b.GENERIC_COLUMN 
       --and a.GENERIC_COLUMN2 = b.GENERIC_COLUMN2 
       --and a.NULL_COLUMN = b.NULL_COLUMN 
       --and a.NULL_COLUMN2 = b.NULL_COLUMN2 
       and  b.rowid > a.ROWID); 

凡SHOULD_BE_UNIQUE和SHOULD_BE_UNIQUE2是不應該被重複的,並具有獨特的列和GENERIC_COLUMN和NULL_COLUMNS可以忽略這麼這麼走出來的查詢列。

當我們在重複記錄中遇到問題時,正在使用此方法。

+0

我建議你學習蒂姆的回答......這根本不回答這個問題。 MySQL afaik中沒有'NVL()'。 – fancyPants

+0

感謝您指出MySQL沒有'code'NVL()'代碼'@fancyPants –

2

這裏的技巧是能夠闡明一個查詢的問題:

SELECT * 
FROM CC t1 
INNER JOIN 
(
    SELECT cc.key1, cc.key2 
    FROM CC cc 
    LEFT JOIN Service s 
     ON cc.key1 = s.sr2 AND 
      cc.key2 = s.sr1 
    GROUP BY cc.key1, cc.key2 
    HAVING COUNT(*) <= 2 OR 
      SUM(CASE WHEN cc.key = 'new' THEN 1 ELSE 0 END) > 2 
) t2 
    ON t1.key1 = t2.key1 AND 
     t1.key2 = t2.key2 

說明:

你原來的兩個子查詢只會如果給定的記錄添加到計數CC,與給定的key1key2值相匹配,並匹配Service表中的相應記錄。我的內部查詢背後的策略是使用GROUP BY來計算髮生這種情況的次數,並使用它來代替子查詢。第一個計數條件是你的底部子查詢,第二個是頂部。

內部查詢查找對應於應保留的記錄的所有key1,key2CC。並且認識到這兩列是您原始查詢中唯一的標準,用於確定是否保留了CC中的記錄。然後,這個內部查詢可以再次加入CC以獲得最終結果集。

在性能方面,即使這個答案可能會讓人有所期待,但它應該比一個大規模的相關子查詢更好,這就是你所擁有的。

+0

速度沒有太大的提高,您能告訴我我應該使用什麼樣的索引「cc」。現在查詢不使用任何索引 –

+0

你有'key1','key2','sr1'和'sr2'上的索引嗎? –

+0

我有「索引'service_index'('sr2','sr1')」 –

0

有了你給我們的信息有限,這可能是使用一個重寫「簡化」的邏輯:

SEELCT * 
    FROM CC NATURAL JOIN 
     (SELECT key1, key2, COUNT(*) AS tally 
      FROM Service 
      GROUP 
      BY key1, key2) AS t 
WHERE key3 = 'new' OR tally <= 2; 

不知道它是否會表現得更好,但可能給你的下一步該怎麼嘗試一些想法?

相關問題