2016-05-29 5 views
4

Ich versuche, mehrere Werte mit einem Grenzwert auszuwählen.So erhalten Sie maximal zwei Einträge für jeden Namen in der WHERE-Klausel

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

Ich verstehe, dass diese Abfrage nicht wie erforderlich funktioniert, aber es ist nur ein Beispiel. Ich kann nicht ganz meinen Kopf wickeln um auf die Situation

Meine gewünschte Ausgabe ist:

id 
1 
5 
4 
8 

Nur um deutlich zu machen, LIMIT zurückkehren {Limit} Zeilen pro Variable.

LIMIT 3 zurückkehren würde 3 Zeilen pro

id 
1 
5 
6 
4 
8 

Tabelle:

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

Ihre Anforderung ist also: Sie möchten höchstens zwei Einträge für jeden Namen? – 1000111

+0

Wo wird entschieden, dass 6 ausgelassen wird? – e4c5

Antwort

3

Hier ist die Abfrage:

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; 

Hinweis: Sie müssen hier die Grenze setzen WHERE t.rank < LIMIT


SQL FIDDLE DEMO


die obige Abfrage auf Ihrer Beispieldaten ausführen, werden Sie eine Ausgabe wie unten erhalten:

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

Erläuterung:

1) Erste Sortieren Sie die Daten basierend auf name aufsteigend

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

Ergebnis:

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

2)@prevName Variable verfolgen wird, wenn der Name schon vorher gesehen wird.

3)@nameRank Variable wird für jeden Namen eine Rangnummer vergeben. Wenn der aktuelle Name bereits gesehen wird, wird ihm eine inkrementierte Nummer zugewiesen. (wie Rollennummer).

4) Mit Hilfe der oben genannten zwei Variablen der Zwischentabelle wie folgt aussehen würde:

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) Da Sie höchstens zwei Einträge pro Namen wollen, so dass Sie benötigen, filtern diese Daten basieren auf rank < 2

0

Warum Sie union wie diese nicht verwenden:

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

Achten Sie auf die ( Klammern.

+0

Benötigen Sie eine 'Order by name, ID' am Ende –

+0

Sie brauchen auch eine SELECT-Abfrage für jeden Benutzer in' WHERE IN (.....) 'Klausel und später gewerkschaftlich sie. – 1000111

+0

Nein, Sie brauchen keine 'Order By'-Klausel, weil Sie die Namen bereits in der von Ihnen gewünschten Reihenfolge eingegeben haben. @ ringø – wajeeh

Verwandte Themen