2016-05-25 4 views
3

machen Ich habe 2 Tabellen: Benutzer und ihre Punkte.Wie komplizierte SQL-Abfrage in Doktrin

Benutzer haben Felder:

  • id

  • Name

Punkte haben Felder:

  • id

  • start_date

  • end_date

  • count_of_points

  • User_id

So einige Benutzer haben oder nicht Punkte. Punkteeinträge nach Zeitintervall (von start_datum bis end_datum) und Anzahl der Punkte, die Benutzer in diesem Intervall haben.

Ich brauche Anzeigetabelle durch Gesamtsumme der Punkte in diesem Moment sortierten Benutzer (Zeitstempel muss zwischen start_date und end_date sein) und diesem Summenwert im Hinblick auf später anzuzeigen. Wenn der Benutzer keine Punkte haben müssen diese Zählung gleich 0 sein

Ich habe so etwas wie dies:

$qb = $this->getEntityManager() 
     ->getRepository('MyBundle:User') 
     ->createQueryBuilder('u'); 
    $qb->select('u, SUM(p.count_of_points) AS HIDDEN sum_points') 
     ->leftJoin('u.points', 'p') 
     ->orderBy('sum_points', 'DESC'); 
$qb->groupBy('u'); 
     return $qb->getQuery() 
      ->getResult(); 

Aber dies sind keine Grenzen gesetzt haben nach den gewünschten Zeitraum und haben kein Feld für Summe Punkte, die ich im Hinblick verwenden können vom Objekt.

Ich habe versucht, zu finden, wie diese Aufgabe zu lösen, und ich habe so etwas wie dies in SQL:

SELECT u.*, up.points FROM users AS u LEFT OUTER JOIN 
     (SELECT u.*, SUM(p.count_of_points) AS points FROM `users` AS u 
     LEFT OUTER JOIN points AS p ON p.user_id = u.id 
     WHERE p.start_date <= 1463578691 AND p.end_date >= 1463578691 
    ) AS up ON u.id = up.id ORDER BY up.points DESC 

Aber diese Abfrage geben Sie mir nur Benutzer mit Einträgen in Punktetabelle, so dass ich glaube, ich muss eine andere JOIN um Benutzer ohne Punkte hinzuzufügen. Es ist eine komplizierte Abfrage. Ich habe keine Ahnung, wie dies in Doktrin implementiert wird, da DQL interne Abfragen mit LEFT JOIN nicht verwenden kann.

Vielleicht gibt es andere Möglichkeiten, diese Aufgabe zu lösen? Vielleicht ist mein Tabellenschema falsch und ich kann das anders machen?

Antwort

1

EDIT: habe die Datumsbedingungen vergessen. Korrigierte Antwort:

Im Klar MySQL Ihre Abfrage würde wie folgt aussehen:

SELECT u.id, u.name, COALESCE(SUM(p.count_of_points),0) AS sum_points 
FROM Users u 
LEFT JOIN Points p ON p.user_id=u.id 
WHERE (p.start_date <= 1463578691 AND p.end_date >= 1463578691) OR p.id IS NULL 
GROUP BY u.id 
ORDER BY sum_points DESC 

Die COALESCE-Funktion die erste nicht NULL Argument zurückschickt, so dass, wenn ein Benutzer Punkte nicht haben, würde die Summe in NULL, aber die COALESCE in 0.

Ich bin mir nicht sicher, ob die Übersetzung der Lehre Query Builder verwenden, aber man könnte versuchen:

$qb = $this->getEntityManager()->createQueryBuilder(); 

$qb->select('u') 
    ->addSelect('COALESCE(SUM(p.count_of_points),0) AS sum_points') 
    ->from('User', 'u') 
    ->leftjoin('u.points', 'p') 
    ->where('(p.start_date <= ?1 AND p.end_date >= ?1) OR p.id IS NULL') 
    ->groupBy('u.id') 
    ->orderBy('sum_points','DESC') 
    ->setParameter(1, $date_now); 
+0

Leider Ihre Variante nur Benutzer mit Punkteinträgen gibt. –

+0

Die einfache SQL oder die DQL-Abfrage? Weil ich das einfache SQL getestet habe, und es gibt alle Benutzer, einschließlich solche ohne Punkte. – scandel

+0

Es ist DQL-Abfrage. –