2009-07-20 10 views
5

グループ内のレコードのサイズを制限したいのですが、これは私の試行です、どうすればいいのですか?グループ内のmysqlの制限?

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

ERROR 1064(42000):あなたは、あなたのSQL構文でエラーが発生しています。集約関数のために使用されていることにより、ラインで「タイプによってグループ」1

+0

私はあなたが望むのは 'グループ'ではなく 'それぞれのアカウントタイプを5つまでリストアップしたいのですが、そうですか? – Plutor

+0

はい、それを達成する方法は? – omg

+2

「Just By The Way」では、クエリの「終わり」にLimitを置く必要があります。 –

答えて

0

グループを近くを使用する 権利構文についてはMySQLサーバのバージョンに対応するマニュアル (合計、平均値...)

をチェック

Isを使用すると、集約結果をグループに分割できます。これらの機能のいずれかを使用していません。

0

私はあなたがグループの制限を使うことができるとは確信していません。グループbyが1つの行/値を返すサブ選択である場合は、おそらくそれを使用できます。たとえば、次のように

選択* fooの順とすることによって、私はちょうどこれが仕事と推測してい

(foo2は制限1からfoo2.idを選択します)。

1

GROUP BY句の後ろにLIMIT句を配置してください。

EDIT:これは最大の残高と、各タイプの最大5つのアカウントを返す

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

:これを試してみてください。

+0

それは私が欲しいものではない... – omg

1

全体的な結果セットの各グループ内で返される行の数を制限したいと思われます。これは、うまくスケーリングする方法では困難です。 1つの手法は、一致する行のみが必要なトップ/ボトムNになるような条件で、同じテーブルに対してN個の結合を実行することです。

this pageは、それぞれのグループでトップ5を返すことは、醜い高速になるだろうが、ソリューションにいくつかの追加の洞察を提供するかもしれません。

0

typeがインデックスに登録されていない場合はsloooowwwwになりますが、これはおそらくトリックです。そして、一つでもして、それは特に高速ではないのです。

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; 

より良い賭けはtypeでちょうどorderリストになり、その後、あなたはしたくない行を削除するには、ビジネスレイヤでループを使用します。

5

集計関数(および必要なGROUP BY)のポイントは、多くの行を1つの行に変換することです。

基準:account_balance

によって特定の口座タイプのトップ5あなたは本当にただのトップ5普通預金口座とトップ5 chequingアカウントとトップ5 USD口座などをしたいのであれば、あなたが必要なものより、このようなものです
SELECT account_type, account_balance FROM accounts WHERE account_type='savings' 
    ORDER BY account_balance DESC LIMIT 5 
UNION 
SELECT account_type, account_balance FROM accounts WHERE account_type='chequing' 
    ORDER BY account_balance DESC LIMIT 5 
UNION 
SELECT account_type, account_balance FROM accounts WHERE account_type='USD' 
    ORDER BY account_balance DESC LIMIT 5; 

これはあまり面白いわけではありませんが、スクリプトを使用してSQLを構築すると、account_typesを継承してクエリーを連結することは簡単です。

5

私は、番号の行を使用して、いくつかの運を持っていた:

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; 

これはあなたitem_typeあたり2件の結果が得られます。 (一つの落とし穴:。そうしないと、行番号が着実に高く高くなりますとrow_number < 3制限は動作しません。あなたが最初の2つのsetステートメントを再実行してください

私はにリンクされているa coupleof postsから一緒にこれをつなぎSO上other answers

+1

これは最高の答えです。あなたができることの1つは、 'from items、(SELECT @type:= ''、@ num:= 0)v'のようなものを使用して、別のステートメントではなく結合内で変数を設定することです。これは、複数のステートメントを許可しない環境で役に立ちます。 –

0

dnagirlの答えはほとんどそれを持っていますが、何らかの理由では、MySQLの私のバージョンは、最初LIMIT'dセットを返します。それを回避するために、@、私はサブクエリ

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 
に各ステートメントを置きます

これはm最終結果セットに各セットの結果を戻します。さもなければ、私は最初のクエリから最初の5つしか得られませんでした。私のバージョンのMySQLのファンクであればわかりません。