Frage

Ich brauche diese DB abzufragen jede Zeile zu erhalten, sondern auch die Summe von einem der Spaltenwerte der Ergebnisse. Ich konnte php den Gesamtwert zu erhalten, aber dann würde ich brauche zwei Schleifen zu laufen, man die insgesamt zu erhalten (die über den Ergebnissen an der Spitze geht). Also würde ich die Abfrage vorziehen, es zu fangen und nur eine „total“ Reihe, aber der einzige Weg, ich es bekommen habe, ist die Arbeit mit einer Unterabfrage, die im Wesentlichen eine Wiederholung der ursprünglichen Abfrage. Gibt es einen besseren Weg?

SELECT 
CONCAT(u.firstname, ' ', u.lastname ) name, u.id, s.description, s.shiftstart, s.shiftend, 
    (SELECT 
    SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600
    FROM shifts
    WHERE id =  '$user'
    AND DATE( shiftstart )
    BETWEEN '$start'
    AND '$end') total
FROM shifts s
INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = '$user'
AND DATE( shiftstart )
BETWEEN '$start'
AND '$end'
ORDER BY shiftstart

Die oben genannten Arbeiten und Ausgänge:

name        id     description  shiftstart             shiftend               total
Joe User    joeuser    Stuff    2009-01-05 07:45:00    2009-01-05 12:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-05 13:00:00    2009-01-05 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 07:45:00    2009-01-06 10:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 10:45:00    2009-01-06 12:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 13:30:00    2009-01-06 14:30:00    39.5000
Joe User    joeuser    Stuff    2009-01-06 14:30:00    2009-01-06 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-07 09:45:00    2009-01-07 14:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-07 15:00:00    2009-01-07 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-08 08:00:00    2009-01-08 12:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-08 13:15:00    2009-01-08 17:00:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 07:45:00    2009-01-09 10:45:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 11:45:00    2009-01-09 15:15:00    39.5000
Joe User    joeuser    Stuff    2009-01-09 15:15:00    2009-01-09 17:00:00    39.5000

Das ist, was ich brauche, aber wahrscheinlich nicht der beste Weg, um es zu bekommen.

War es hilfreich?

Lösung

MySQL unterstützt eine spezielle Gruppe-by-Modifikator genannt ROLLUP- .

SELECT CONCAT(u.firstname, ' ', u.lastname ) name, u.id, 
  s.description, s.shiftstart, s.shiftend, 
  SUM( TIME_TO_SEC( TIMEDIFF( shiftend, shiftstart ) ) ) /3600 total
FROM shifts s INNER JOIN users u ON ( s.id = u.id )
WHERE s.id = ? AND DATE( shiftstart ) BETWEEN ? AND ?
GROUP BY u.id, s.shiftstart WITH ROLLUP
ORDER BY shiftstart;

Andere Tipps

Der bessere Weg ist dies mit dem Code zu tun. Menschen immer darauf bestehen SQL über die Verwendung, die eine relationale Algebra ist, für verfahrenstechnische Aufgaben zu tun. Verfahrens-ness auf SQL Schuhanzieher Der Versuch ist immer eine schlechte Idee, sowohl in Bezug auf Komplexität und Leistung. Nehmen Sie diese Beratung durch einen professionellen DBA.

Führen Sie zwei Abfragen aus dem Code. Ausgabe der größeren Satz zuerst, dann die gesamte Zeile in welcher Format, das Sie sich wünschen. Ihre Anfragen werden kleiner und einfacher, Ihre Leistung zu verbessern und Sie werden die Ausgabe, die Sie wünschen, erhalten.

Einige andere Beratung - Speicherplatz ist billig und die meisten Datenbanktabellen sind weit häufiger gelesen, als sie geschrieben sind. Richten Sie ein Insert / Update-Trigger (wenn möglich in MySQL) eine eigene Spalte mit berechneten Feldern wie „CONCAT(u.firstname,' ',u.lastname)“ zu füllen und verwenden, die für Abfragen. Per-Reihe sind Funktionen nicht skalierbar und wird Ihre DBMS Leistung töten, wie es größer wird.

Alles kann durch den Vergleich besser sein; die Frage ist, Vergleich zu dem, was, nicht wahr?

Die Schlüsselfrage Sie angegeben ist, dass Sie die gesamte an der Spitze der Ergebnisse wollte; Crystal Reports, und andere Anwendungen, verwalten diese Art von Magie durch einen Motor 2 Pass zu sein. Erster Durchgang wird die Summen.

Es gibt Kompromisse mit jeder Lösung. Wenn Sie eine separate „total“ Reihe bekommen, dann der Empfang App müssen sie entweder Streifen der Ergebnisse aus oder einem anderen Trick, es zu verstecken spielen.

Eine Möglichkeit, die eine Option sein, wenn Sie nicht für eine Million Treffer / hr Website zu schreiben, ist einfach zu 2 Anrufe tätigen - einen für die Overhead-Informationen, wie der Namen, Gesamtzeit, etc, dann für die Details ... Es scheint aus der Abfrage Sie eine einzelne Person, die Ergebnisse auswählen.

Wir sind alle für das Speichern von Overhead und Bandbreite, aber manchmal einfach besser ...

EDIT: Pax mich schlagen auf die Schaltfläche "Speichern" ... lol ...

Mit der MySQL-Erweiterung zur Verfügung gestellt genau zu diesem Zweck, wie in Bill Karwin Antwort beschrieben (was ich habe mich upvoted).

Wenn nicht verfügbar waren, Option 2 wäre eine andere SQL-Anweisung sein: SELECT SUM ...) SQL wirklich optimiert ist für diese Art der Sache äußerst effizient zu sein, im Vergleich zu allen verfahrens-Code Looping sind Sie wahrscheinlich zu schreiben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top