2016-04-18 7 views
0

Ich habe Probleme beim Konvertieren meiner Budgetübersichtsansicht vom letzten Jahr auf dieses Jahr. Hier ist die SELECT-Anweisung für die Ansicht des letzten Jahres, die Dinge richtige zurück:Wie erweiterte Einschränkungen auf einem LINKEN JOIN ordnungsgemäß verwendet werden, um alle Ergebnisse auf der linken Seite zurückzugeben

SELECT 
    b.Category AS Category, 
    b.Amount AS Amount, 
    SUM(e.Amount) AS Spent, 
    (b.Amount - SUM(e.Amount)) AS Remaining 
FROM 
    Budget AS b LEFT JOIN Expenditure AS e 
    ON (
     b.Category = e.BudgetCategory 
     AND e.Date < '2016-01-01' 
     AND e.Date > '2015-01-01' 
     AND b.Year = 2015 
    ) 
GROUP BY e.BudgetCategory 

Wenn ich die Daten bearbeiten, so dass es in diesem Jahr umfasst, dann bricht es die Ansicht, da keine Datensätze in der Ausgaben-Tabelle sind, die von dieses Jahr. Es gibt nur den ersten Datensatz aus Budget zurück und die Felder, die auf Ausgaben angewiesen sind, sind NULL. Ich möchte, dass alle Datensätze aus dem Budget zurückgegeben werden und NULL für alle Felder angezeigt wird, die sich auf die Ausgaben beziehen, die von den Ausgaben abhängen.

Was im letzten Jahr Ansicht kehrt:

Category | Amount | Spent  | Remaining 
-------------------------------------------------------------- 
Contractors | 0.00  | NULL  | NULL (this is correct) 
Gasoline | 250.00 | 240.00 | 10.00 
Merchandise | 2000.00 | 1900.00 | 100.00 

etc ...

Was es für dieses Jahr ist die Rückkehr:

Category | Amount | Spent | Remaining 
-------------------------------------------- 
Contractors | 4000.00 | NULL | NULL 

Was ich es (während der Ausgaben zurückkehren möge Ergebnisse bleiben 0):

Category | Amount | Spent | Remaining 
-------------------------------------------- 
Contractors | 4000.00 | NULL | NULL 
Gasoline | 300.00 | NULL | NULL 
Merchandise | 2500.00 | NULL | NULL 

etc ...

Was mache ich falsch?

+0

Ist 'Kategorie' ein eindeutiger Schlüssel (vielleicht der Primärschlüssel) der Tabelle' Budget'? Oder kann es mehrere "Budget" -Rekorde für dieselbe "Kategorie" geben? –

Antwort

1

Sie müssen durch die Spalten in der ersten Tabelle eines left join aggregieren:

SELECT b.Category AS Category, b.amount, 
     SUM(e.Amount) AS Spent, 
     (b.Amount - SUM(e.Amount)) AS Remaining 
FROM Budget b LEFT JOIN 
    Expenditure e 
    ON b.Category = e.BudgetCategory AND 
     e.Date < '2016-01-01' AND 
     e.Date >= '2015-01-01' 
     b.Year = 2015 
GROUP BY b.Category, b.amount; 

Kleine Änderungen:

  • Ich änderte den Zustand in der ON Klausel >=. Es scheint nur vernünftiger.
  • Ich fügte b.amount der GROUP BY hinzu.
+0

Ich fand, dass die Abfrage funktioniert auch durch Gruppierung von e.BudgetCategory und b.Category oder nur b.Category allein. Ich gruppiere ursprünglich nach e.BudgetCategory, da die Dinge aus der Tabelle addiert werden. Was ist eine Erklärung auf hoher Ebene der hier ablaufenden Logik? Warum muss die Gruppe auf irgendeiner Seite des Joins sein? – Shadouts

+0

@Shadouts: Dies liegt daran, dass Sie sich der Tabelle "Ausgaben" äußerlich anschließen. Wenn in dieser Tabelle für ein Budget keine Übereinstimmung gefunden wird.Kategorie im angegebenen Zeitraum, erhalten Sie einen Dummy-Record mit * allen * Feldern NULL, einschließlich BudgetCategory. Sie haben also nicht nach der Kategorie gruppiert, nach der Sie tatsächlich gesucht haben (Budget.Category). –

+0

@Shadouts: Was "Gruppierung nach e.BudgetCategory und b.Category oder nur b.Category alone" betrifft, liegt das daran, dass es nur einen * Rekord pro Kategorie pro Jahr gibt, wie Sie in einem Kommentar zu meiner Antwort gesagt haben. Wenn dies nicht der Fall wäre, würden Sie einen der willkürlich ausgewählten Beträge der Kategorie erhalten. Gordon konnte nicht wissen, dass Kategorie + Jahr in Ihrer Tabelle einzigartig ist, also legte er budget.amount in die GROUP BY-Klausel, um sicher zu stellen, dass ein solcher Fehler nicht automatisch eingeführt wird. Darüber hinaus garantiert diese Spalte in GROUP BY, dass die Abfrage sogar mit dem ONLY_FULL_GROUP_BY-Modus in MySQL ausgeführt wird. sonst wäre es nicht. –

1

Dies ist ein kleiner Fehler. Anstatt nach b.Category zu gruppieren, gruppieren Sie sich fälschlicherweise nach e.BudgetCategory.

SELECT 
    b.Category AS Category, 
    b.Amount AS Amount, 
    SUM(e.Amount) AS Spent, 
    (b.Amount - SUM(e.Amount)) AS Remaining 
FROM 
    Budget AS b LEFT JOIN Expenditure AS e 
    ON (
     b.Category = e.BudgetCategory 
     AND e.Date < '2016-01-01' 
     AND e.Date > '2015-01-01' 
    ) 
WHERE b.Year = 2015 
GROUP BY b.Category; 

zog ich die Kriterien auf b.Year-WHERE Lesbarkeit zu verbessern, da es keine Kriterien für die äußere Expenditure Join ist.

Ist Category ein eindeutiger Schlüssel für Tabelle Budget übrigens? Andernfalls erhalten Sie eine der willkürlich ausgewählten Beträge der Kategorie. Vielleicht möchten Sie lieber ein Aggregat wie SUM(b.Amount) stattdessen.

+0

b.Amount ist eine Gesamtbudgetobergrenze, Summe (e.amount) ist die Summe aller ausgegebenen Gelder aus dieser Kategorie. b.Kategorie ist von Jahr zu Jahr einzigartig, aber e.BudgetCategory ist eine Art Auslandsbeziehung zu b.category. – Shadouts

+0

Ah, okay, dann ist alles in Ordnung. Sie erhalten einen Budget-Datensatz pro Kategorie für das Jahr 2015, also gibt es keine Mehrdeutigkeit in Bezug auf den Betrag. –

Verwandte Themen