2014-10-07 73 views
0

我目前正在進行一些mysql查詢的項目。項目中的所有mysql查詢都是由其他開發人員完成的。不管怎麼說,我跟他已經做了以下的查詢有點混亂:如何提高這個mysql查詢處理的速度

SELECT MIN(s_date) AS s_date, 
     client_id 
FROM tb1 
WHERE flag = 1 
    AND client_id NOT IN (
     SELECT DISTINCT client_id 
     FROM tb1 
     WHERE flag = 0 
    ) 
GROUP BY client_id; 

查詢的第一部分,如果標誌= 1,第二部分是檢查不檢查是(標誌= 0)。我認爲這是多餘的,因爲旗= 1,它不能是0.我不明白該查詢的邏輯。而且我認爲NOT IN有點慢(我的數據庫需要2秒)。

請解釋一下這個查詢意味着什麼,以及如何簡化和改進它。

+1

使用EXPLAIN另一種創造性的選擇查看你的查詢使用了什麼索引,然後考慮調整你的索引 – 2014-10-07 16:16:14

+2

你也可能發現使用JOIN查詢比使用子查詢更有效 – 2014-10-07 16:16:49

+0

@Mihai在不知道tb1的實際結構的情況下,我不能說對於某些;但最常見的做法是將'id'作爲主鍵,'client_id'將是一個外鍵 – 2014-10-07 16:19:36

回答

1

您似乎總結了旗子從不0的客戶端。查詢更簡單地寫爲:

SELECT MIN(s_date) s_date, 
     client_id F 
FROM tb1 
WHERE flag in (0, 1) 
GROUP BY client_id 
HAVING SUM(flag = 0) = 0; 

這也可能會提高性能。

+0

+1。與使用反連接或NOT EXISTS謂詞的查詢相比,此表單可能會提供更好的性能。通過這個查詢,MySQL可能會有效地使用索引'ON tbl(client_id,s_date,flag)'。 – spencer7593 2014-10-07 16:35:45

+0

真棒,它只需要0.02秒得到相同的結果,歡呼聲:) – agthumoe 2014-10-08 08:25:04

+0

但tbh,我真的不明白的代碼,如果你不介意,請詳細說明它。謝謝 – agthumoe 2014-10-08 08:26:14

0

在大多數數據庫中,使用「不在」是簡單,直觀但緩慢的。有時候你可以這樣解決:

where myfield in 
(select myfield 
where I want it 
minus 
select myfield 
where I want to exclude it) 

有些數據庫使用除了而不是minus之外的單詞。我不認爲這與MySQL的工作,所以你必須做這樣的事情:

select somefields 
from sometables 
left join (
select idfield, someOtherField 
from blah 
where I want to exclude it 
) temp on sometable on sometable.idfield = temp.idfield 
and temp.someOtherField is null 
0

這裏是你怎麼想起來:

IN子選擇你發現的client_id的有名單至少有一條記錄的標誌位爲0.

然後,您從主查詢中排除該id列表。

所以,如果你有這樣的樣本數據:

client_id flag s_date 
--------- ---- ------ 
1   1  2014-01-01 
2   0  2014-02-01 
2   1  2014-03-01 
3   0  2014-04-01 
4   1  2014-05-01 
4   1  2014-06-01 

您的查詢只會返回:

s_date  client_id 
------  --------- 
2014-01-01 1 
2014-05-01 4 

其實在您的查詢,冗餘使用的flag實際上是在主查詢。它根本就不需要,因爲你已經在子查詢中消除了任何flag = 0值的所有client_id。

就優化查詢而言。這是其中的一種情況,其中子查詢可能比聯接更快,也可能不是。這實際上取決於數據行的數量,符合子選擇條件的那些行的數量等等(當然假設所有適當的索引都已經到位)。

你可以嘗試自加入這樣看執行更好地爲您:

SELECT 
    MIN(a.s_date) AS s_date, 
    a.client_id AS client_id 
FROM tbl AS a LEFT JOIN (
    SELECT DISTINCT client_id 
    FROM tb1 
    WHERE flag = 0 
) AS b 
ON a.client_id = b.client_id 
WHERE b.client IS NULL 
GROUP BY a.client_id 

也可以嘗試通過@GordonLinoff回答是獲得這個同樣的查詢結果

+0

感謝您的解釋,現在有道理。而你的代碼真的有效。只需1秒即可獲得結果。乾杯 – agthumoe 2014-10-08 08:27:41