2009-07-20 7 views
5

Ich möchte die Größe von Datensätzen innerhalb einer Gruppe begrenzen, und hier ist mein Versuch, wie es richtig geht?mysql limit innerhalb der Gruppe?

mysql> select * from accounts limit 5 group by type; 

ERROR 1064 (42000): Sie haben einen Fehler in der SQL-Syntax; das Handbuch , die für die richtige Syntax verwendet in der Nähe von ‚Gruppe von Typ‘ in Zeile 1

+0

Ich denke, dass was Sie wollen, ist eine 'Bestellung', nicht eine' Gruppe'. Sie möchten bis zu 5 von jedem Kontotyp angeben, oder? – Plutor

+0

ja, wie das zu erreichen? – omg

+2

Just By the Way, müssen Sie das Limit am Ende der Abfrage setzen. –

Antwort

0

Gruppe zu Ihrer MySQL-Server-Version entspricht, die durch für Aggregatfunktionen verwendet wird (Summen, Mittelwert ...)

Ermöglicht es Ihnen, das Gesamtergebnis in Gruppen aufzuteilen. Sie haben keine dieser Funktionen verwendet.

0

Ich bin mir nicht sicher, ob Sie ein Limit in der Gruppe verwenden können. Sie können es wahrscheinlich verwenden, wenn Ihre Gruppe eine Unterauswahl ist, die eine Zeile/einen Wert zurückgibt. Zum Beispiel:

select * from foo, um durch (wählen foo2.id von foo2 Grenze 1)

ich gerade dies bin zu raten, funktionieren würde.

1

Versuchen Sie, die LIMIT-Klausel nach der GROUP BY-Klausel zu platzieren.

EDIT: Versuchen Sie folgendes:

SELECT * 
FROM accounts a1 
WHERE 5 > 
(
    SELECT COUNT(*) 
    FROM accounts a2 
    WHERE a2.type = a1.type 
    AND a2.balance > a1.balance 
) 

Das mit den größten Salden höchstens 5 Konten jeder Art zurückgibt.

+0

das ist nicht, was ich will ... – omg

1

Es scheint so, als ob Sie die Anzahl der Zeilen begrenzen möchten, die innerhalb jeder Gruppe Ihrer Gesamtresultate zurückgegeben werden. Dies ist auf eine gut skalierbare Weise schwierig. Eine Technik besteht darin, N Joins in derselben Tabelle mit den Bedingungen auszuführen, dass die einzigen übereinstimmenden Zeilen die gewünschte obere/untere N sind.

this page kann einige zusätzliche Einblicke in Ihre Lösung bieten ... obwohl die Rückkehr der Top 5 in jeder Gruppe wird hässlich schnell werden.

0

Dies wird wahrscheinlich den Trick tun, obwohl, wenn type nicht indiziert ist, wird es sloooowwww sein. Und selbst mit einem, dann ist es nicht besonders schnell:

SELECT a.* 
FROM accounts a 
    LEFT JOIN accounts a2 ON (a2.type = a.type AND a2.id < a.id) 
WHERE count(a2.id) < 5 
GROUP BY a.id; 

Eine bessere Wette nur order der Liste von type sein würde und dann eine Schleife in der Business-Schicht verwenden, um die Zeilen zu entfernen, die Sie nicht wollen.

5

Der Punkt einer Aggregatfunktion (und die GROUP BY es erfordert) besteht darin, viele Zeilen in eine Zeile zu verwandeln. Also, wenn Sie wirklich nur die Top-5-Sparkonten wollen und die Top-5 chequing Konten und die Top-5 USD Konten usw., was Sie brauchen, ist mehr wie folgt aus:

Kriterien: top 5 von bestimmten Kontotyp von account_balance

Es ist nicht schön, aber wenn Sie das SQL mit einem Skript erstellen, dann Subbing in den account_types und Verkettung zusammen eine Abfrage ist einfach.

5

Ich habe etwas Glück mit nummerierten Reihen hatte:

set @type = ''; 
set @num = 0; 

select 
    items.*, 
    @num := if(@type = item_type, @num + 1, 1) as dummy_1, 
    @type := item_type as dummy_2, 
    @num as row_number 
from items 
group by 
    item_type, 
    row_number 
having row_number < 3; 

Dies Sie pro item_type 2 Ergebnisse geben. (Ein Gotcha: stellen Sie sicher, erneut ausführen, die ersten beiden set Aussagen sonst Ihre Zeilennummern stetig höher bekommen und höher und die row_number < 3 Einschränkung funktioniert nicht

ich dies aus a coupleof posts zusammen genäht, die in Verbindung gebracht wurden. other answers auf SO.

+1

Dies ist die beste Antwort. Eine Sache, die Sie tun können, ist, etwas wie dieses zu verwenden: 'von den Einzelteilen, (AUSWAHL @Type: = '', @num: = 0) v' und dann können Sie die Variablen innerhalb des Anschlusses anstatt in einer unterschiedlichen Aussage einstellen . Dies kann in Umgebungen hilfreich sein, in denen mehrere Anweisungen nicht zulässig sind. –

0

@ Antwort des dnagirl es fast, aber aus irgendeinem Grund, gibt meine Version von MySQL nur den ersten Satz LIMIT'd. um das zu bekommen, habe ich jede Anweisung in einer Unterabfrage

SELECT * FROM (
    SELECT account_type, account_balance FROM accounts WHERE account_type='savings' 
     ORDER BY account_balance DESC LIMIT 5 
) as a 
UNION 
SELECT* FROM (
    SELECT account_type, account_balance FROM accounts WHERE account_type='chequing' 
     ORDER BY account_balance DESC LIMIT 5 
) as b 
UNION 
SELECT * FROM (
    SELECT account_type, account_balance FROM accounts WHERE account_type='USD' 
     ORDER BY account_balance DESC LIMIT 5 
) as c 

Dies ergab m Die Ergebnisse jedes Satzes im Ergebnissatz zurückgeben. Sonst hätte ich nur die ersten 5 von der ersten Abfrage und nichts anderes bekommen - nicht sicher, ob es nur ein MySQL-Funk mit meiner Version ist