2016-05-29 57 views
4

我試圖完成的是選擇具有限制的多個值。如何在where子句中爲每個名稱獲取至多兩個條目

SELECT id FROM table WHERE name IN ('Tom', 'Tommy') LIMIT 2 

我明白這個查詢不會按需要工作,但它只是一個例子。 我不能完全包住我的頭周圍的情況

我所需的輸出是:

id 
1 
5 
4 
8 

只是爲了說清楚,LIMIT會返回{}限行每個變量。

LIMIT 3將每

id 
1 
5 
6 
4 
8 

表返回3行:

id, name 
1, Tom 
2, Jeff 
3, Jason 
4, Tommy 
5, Tom 
6, Tom 
7, Jeff 
8, Tommy 
+0

所以你的要求是:你最多需要兩個條目的每個名字? – 1000111

+0

禾如何決定6是被遺漏的一個? – e4c5

回答

3

這裏的查詢:

SELECT 
t.id, 
t.name 
FROM 
(
    SELECT 
    id, 
    `name`, 
    IF(@prevName = `name`, @nameRank := @nameRank + 1, @nameRank := 0) rank, 
    @prevName := `name` 
    FROM your_table, (SELECT @prevName := NULL, @nameRank := 0) var 
    WHERE `name` IN ('Tom','Tommy') 
    ORDER BY `name`,id 
) t 
WHERE t.rank < 2 
ORDER BY t.id; 

注:這裏需要把限制WHERE t.rank < LIMIT


SQL FIDDLE DEMO


運行在您的樣本數據上面的查詢,你會得到一個輸出象下面這樣:

| id | name | 
|----|-------| 
| 1 | Tom | 
| 4 | Tommy | 
| 5 | Tom | 
| 8 | Tommy | 

說明:

1)第一根據數據對數據進行排序name以升序

SELECT 
    id, 
    `name` 
    FROM your_table 
    WHERE `name` IN ('Tom','Tommy') 
    ORDER BY `name` 

結果:

id name 
1 Tom 
5 Tom 
6 Tom 
4 Tommy 
8 Tommy 

2)@prevName變量將跟蹤如果名稱已見過。

3)@nameRank變量將爲每個名稱分配一個等級號碼。如果當前的名字已經是一個可見的名字,那麼它會爲它分配一個遞增的數字。 (如卷號)。

4)通過上述兩個變量的幫助下,中間表看起來象下面這樣:

id name rank 
1 Tom  0 (seen first time so rank = 0) 
5 Tom  1 (seen second time so rank = rank + 1 ; rank = 1) 
6 Tom  2 (seen third time so rank = 2) 
4 Tommy 0 (seen first time so rank = 0) 
8 Tommy 1 (seen second time so rank = 1) 

5)既然你想在每名最多兩個條目,這樣你需要篩選基於rank < 2

0

這些數據爲什麼你不使用union這樣的:

(SELECT id FROM table WHERE name like 'Tom' LIMIT 2) 
UNION 
(SELECT id FROM table WHERE name like 'Tommy' LIMIT 2) 

小心(括號。

+0

在末尾需要一個'按名稱,編號排序' –

+0

您還需要爲'WHERE IN(.....)'子句中的每個用戶選擇一個查詢,並稍後將它們組合起來。 – 1000111

+0

不,你不需要'Order By'子句,因爲你已經按照你想要的順序放置了名字。 @ringø – wajeeh