2013-08-10 12 views
8

私は今これを理解しようとしてきましたが、それを機能させるようには見えません。私はこれに似た表を持っています。Eloquentを使用してグループ化された結果を注文するには?

表:問題

id yearly_issue year stock created_at  updated_at  magazine_id 
1 10    2000 1  [timestamp]  [timestamp]  3 
2 12    1994 6  [timestamp]  [timestamp]  10 
3 36    2007 10  [timestamp]  [timestamp]  102 
4 6    2002 7  [timestamp]  [timestamp]  7 
5 6    2002 2  [timestamp]  [timestamp]  5 
6 12    2003 9  [timestamp]  [timestamp]  10 
7 11    2003 12  [timestamp]  [timestamp]  10 

私の問題は、私はそれをソートする必要があるということですが、私は各マガジン(列magazine_id)のいずれかを取得したい(簡単!)。今のよう

マイ雄弁クエリは次のとおりです。

$issues = Issue::where('stock', ($all ? '>=' : '>'), 0) 
    ->orderBy('year', 'desc') 
    ->orderBy('yearly_issue', 'desc') 
    ->take($perpage) 
    ->get(); 

私はgroupBy('magazine_id')を追加することに役立つだろうと思ったが、それは部分的にしか私を助けているように思えます。結果は正しい順序ではありません。ですから、私の疑問は次の通りです。これを回避する方法は簡単ですか?

私は同様の質問に対するさまざまな回答を試してきましたが、私はそれを完全に実装することはできません。

Retrieving the last record in each group

または

How to get the latest record in each group using GROUP BY?

詳細なヘルプははるかに高く評価されるだろう。

EDIT:

SELECT i1.*, c.name AS image, m.title AS title 
FROM issues i1 
INNER JOIN covers c ON i1.id = c.issue_id 
INNER JOIN magazines m ON i1.magazine_id = m.id 
JOIN (SELECT magazine_id, MAX(year) year, MAX(yearly_issue) yearly_issue FROM issues GROUP BY magazine_id) i2 
ON i1.magazine_id = i2.magazine_id 
AND i1.year = i2.year 
-- AND i1.yearly_issue = i2.yearly_issue 
WHERE i1.stock ($all ? '>=' : '>') 0 
ORDER BY i1.year DESC, i1.yearly_issue DESC 
LIMIT $perpage 

はしかし、それがすべてで私に望ましい結果を与えていない: 私は現在、午前最も近いがこれです。

答えて

13

SELECT句にMAX関数を追加する必要があります。これは、各列の順序番号DESCの終了順になります。逆順は、ASCで終了した順番に並べ替えられます。SELECT句には、MIN関数を追加する必要があります。

あなたの雄弁クエリがrawを選択含まれていなければならない:

$issues = DB::table('issues') 
    ->select(DB::raw('id, max(year) as year, max(yearly_issue) as yearly_issue, stock, created_at, updated_at, magazine_id')) 
    ->groupBy('magazine_id') 
    ->orderBy('year', 'desc') 
    ->orderBy('yearly_issue', 'desc') 
    ->take(10) 
    ->get(); 

のみ欠点はあなたが取得したい各列を指定する必要があるということです。 *セレクタを使用しない場合は、select句の集約関数をオーバーライドします。


更新は:SELECT句あまりにも作品に*セレクタ前の集計関数を追加することのように思えます。私は*セレクタが前の集計関数はその列を上書きします置くと思い

->select(DB::raw('*, max(year) as year, max(yearly_issue) as yearly_issue')) 

:これはあなたのように生の選択を書き換えることを意味します。

+1

驚くばかり! =)それは私の週末を救った。 – Andreas

+1

Uooow!それは本当に人生の節約になりました。どうもありがとう! –

+0

ありがとう、これは最高の解決策です。 –

3

私はグルーピングする前に結果を注文する方法を探していましたが、この回答は引き続きポップアップしていました。私の場合、それはユーザーのメッセージ受信箱のためのものでした。私は、彼らが参加していた各メッセージスレッドにユーザーが受け取った最新のメッセージを表示する必要がありました。私のテーブルは次のようになります:

-------------------------------------------------------------------- 
| id | sender_id | receiver_id | message | created_at | updated_at | 
-------------------------------------------------------------------- 
| |   |    |   |   |   | 
-------------------------------------------------------------------- 

この質問に対して受け入れられた回答は、結果をグループ化して並べ替えます。 created_atフィールドを降順に並べ替える前に、グループ化する前に各スレッドから最新のメッセージを取得する必要がありました。で

select * 
    from `UserTable` 
where userId=3 
    group by `field` desc 
    order by `dateActivityComplete` ; 

select * from (
    select * from `messages` 
    order by `created_at` desc 
) as sub 
group by `sender_id` 
+1

ありがとう、私の特定の必要性のために働いていなかった - > tosqlパーサーはパラメータを非常によく解析していませんが、単純な生のSQLクエリを実行すると、自分の解決策:) –

0

MySQLでは、あなたがこのような何かを行うことができます。

$sub = $query->orderBy('created_at', 'desc'); 
return $query->select('*') 
      ->from(DB::raw("({$sub->toSql()}) as sub")) 
      ->groupBy('sender_id'); 

これは、次のクエリを作成:とにかく、ここでは掘削の多くの後、私の最終的な解決策でしたあなたは次のようなことを雄弁に語ります: - > groupBy( '​​field'、 'desc')しかし、groupByを注文することは、

生のクエリ、または場合によってはmax関数を使用する必要がある場合もあります。

ウェイド

関連する問題