2013-08-10 13 views
8

Ich habe schon seit einiger Zeit versucht, das herauszufinden, und kann es einfach nicht funktionieren lassen. Ich habe einen Tisch, der dem ähnlich sieht.Wie gruppiere ich Ergebnisse mit Eloquent?

Tabelle: Probleme

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 

Mein Problem ist, dass ich es sortieren muß (ganz einfach!), Aber ich möchte nur eine von jedem Magazin (Spalt magazine_id) erhalten.

Meine Eloquent Abfrage ab jetzt ist:

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

Ich dachte Zugabe der groupBy('magazine_id') würde helfen, aber es scheint, als ob es nur zum Teil mir hilft. Die Ergebnisse sind nicht in der richtigen Reihenfolge. Meine Frage ist also - gibt es einen leichten Weg dahin?

Ich habe mit verschiedenen Antworten auf ähnliche Fragen experimentiert, aber ich versage es vollständig zu implementieren.

Retrieving the last record in each group

oder

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

Mehr Hilfe sehr geschätzt würde.

EDIT: Die nächstgelegene ich zur Zeit bin, ist dies:

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 

Allerdings ist es mir nicht das gewünschte Ergebnis überhaupt gibt.

Antwort

13

Sie müssen eine MAX Funktion in der SELECT Klausel für jede zu bestellende Spalte in DESC Endreihenfolge hinzufügen. Die umgekehrte Reihenfolge gilt für Spalten, die in der Reihenfolge ASC endend angeordnet sind. Sie müssen MIN Funktion in der SELECT Klausel hinzufügen.

Ihre Eloquent Abfrage muss umfassen eine raw wählen:

$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(); 

Der einzige Nachteil ist, dass Sie jede Spalte, die Sie abrufen möchten angeben müssen. Und verwenden Sie nicht den * Selektor, es überschreibt die Aggregatfunktion in der SELECT-Klausel.


aktualisieren: Scheint, wie das Hinzufügen des * Selektor vor die Aggregatfunktionen in der SELECT Klausel auch funktioniert. Dies bedeutet, dass Sie die rohe wählen umschreiben als:

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

Ich denke, setzen die * Selektor, bevor die Aggregatfunktionen überschreibt ihre Spalten macht.

+1

Super! =) Das hat mein Wochenende gerettet. – Andreas

+1

Uuuuu! Das war wirklich ein Lebensretter. Danke vielmals! –

+0

vielen Dank, das ist die beste Lösung –

3

Ich war auf der Suche nach einer Möglichkeit, Ergebnisse vor der Gruppierung zu bestellen und diese Antwort tauchte immer wieder auf. In meinem Fall war es für den Posteingang eines Benutzers.Ich musste die letzte Nachricht anzeigen, die der Benutzer in jedem Nachrichten-Thread erhalten hat, zu dem er gehört hat. Meine Tabelle sieht folgendermaßen aus:

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

Die akzeptierte Antwort zu dieser Frage gruppiert die Ergebnisse und sortiert sie dann. Ich musste die Ergebnisse nach dem Feld created_at absteigend sortieren, bevor ich sie gruppierte, damit ich die neueste Nachricht von jedem Thread bekam. Wie auch immer, hier war meine letzte Lösung nach viel zu graben:

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

Diese erstellt die folgende Abfrage:

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

Vielen Dank, es hat nicht für meine spezifischen Bedürfnisse funktioniert, der -> Tosql Parser analysiert die Parameter nicht ganz gut, aber das Ausführen einer einfachen rohen SQL-Abfrage löste es für mich, fügte mein hinzu eigene Lösung :) –

0

In MySQL Sie so etwas tun kann:

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

In eloquent würden Sie so etwas tun: -> groupBy ('Feld', 'desc'), jedoch die Bestellung der groupBy scheint nicht eine Option in eloquent das gleiche wie Reihenfolge von ist.

Möglicherweise eine Instanz, in der Sie eine rohe Abfrage oder möglicherweise die max-Funktion verwenden müssen.

Wade

Verwandte Themen