2017-05-14 2 views
1

Problem:MySQL - ausschließen letzten Monat von Gruppe

Die Tabelle Mitarbeiter die Gehaltsinformationen in einem Jahr hält.

Schreiben Sie eine SQL, um die kumulierte Summe des Gehalts eines Mitarbeiters über einen Zeitraum von 3 Monaten zu erhalten, aber den letzten Monat auszuschließen.

Das Ergebnis sollte mit "Id" aufsteigend und dann mit "Monat" absteigend angezeigt werden.

Employee-Tabelle:

| Id | Month | Salary | 
|----|-------|--------| 
| 1 | 1  | 20  | 
| 2 | 1  | 20  | 
| 1 | 2  | 30  | 
| 2 | 2  | 30  | 
| 3 | 2  | 40  | 
| 1 | 3  | 40  | 
| 3 | 3  | 60  | 
| 1 | 4  | 60  | 
| 3 | 4  | 70  | 

Mein Code:

SELECT t1.Id, t1.Month, 
    (SELECT SUM(Salary) 
    FROM Employee AS t2 
    WHERE t1.Id = t2.Id 
    AND t1.Month >= t2.Month) AS Salary 
FROM Employee t1 
WHERE Month <> (SELECT 
      MAX(Month) 
      FROM Employee 
      GROUP BY t1.Id) 
ORDER BY Id, Month DESC; 

Meine Leistung:

| Id | Month | Salary | 
|----|-------|--------| 
| 1 | 3  | 90  | 
| 1 | 2  | 50  | 
| 1 | 1  | 20  | 
| 2 | 2  | 50  | 
| 2 | 1  | 20  | 
| 3 | 3  | 100 | 
| 3 | 2  | 40  | 

Erwartet:

| Id | Month | Salary | 
|----|-------|--------| 
| 1 | 3  | 90  | 
| 1 | 2  | 50  | 
| 1 | 1  | 20  | 
| 2 | 1  | 20  | 
| 3 | 3  | 100 | 
| 3 | 2  | 40  | 

benutzen ich MAX() und GROUP BY() Funktionen den letzten Monat, jede Gruppe auszuschließen, aber es funktioniert nicht für Id = 2.

Gibt es einen Hinweis, wie Sie die folgende Zeile loswerden können?

| 2 | 2  | 50  | 

Vielen Dank im Voraus.

+0

Fast, aber siehe https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me- to-be-a-very-simple-sql-query – Strawberry

+0

Ich entfernte die inkompatiblen Datenbank-Tags Bitte markieren Sie nur mit der von Ihnen verwendeten Datenbank –

+0

Warum sind 'month = 4' Zeilen ausgeschlossen? –

Antwort

1

verwenden Ich denke, diese Antwort am nächsten ist, was Sie in Ihrer ursprünglichen vorhatten Abfrage:

SELECT t1.id, t1.month, 
    (SELECT SUM(salary) 
     FROM employee t2 
     WHERE t1.id = t2.id 
     AND t1.month >= t2.month 
     AND t1.month - t2.month < 3) AS salary 
    FROM employee t1 
WHERE month <> (SELECT MAX(month) 
        FROM employee t3 
        WHERE t3.id = t1.id) 
ORDER by id, month desc; 

Auf den zweiten Blick waren Sie eigentlich ziemlich nah. Ich glaube, das Problem war, dass die "GROUP BY t1.Id "Zeile gruppiert eigentlich nichts, weil t1.Id für jede gegebene Unterabfrage konstant ist, da" t1 "in der äußersten Auswahlanweisung definiert ist. Ersetzen Sie sie durch eine Where-Klausel und begrenzen Sie die Summe auf 3 Monate in der SUM() Abfrage und du bist da.

+0

Es hilft viel! Ich denke, __WHERE__-Klausel kann manchmal als __GROUP BY__ funktionieren, was in diesem Fall die gleiche Idee für die Unterabfrage in der __SELECT__-Anweisung ist. –

1

Diese Abfrage:

SELECT e.Id, e.Month, SUM(e2.Salary) AS 'Salary' 

FROM 
    Employee AS e 

    INNER JOIN Employee AS e2 
     ON e2.Id = e.Id 
     AND e2.Month <= e.Month 

WHERE 
    e.Month <> (SELECT MAX([Month]) FROM Employee WHERE Id = e.Id) 

GROUP BY 
    e.Id, e.Month 

ORDER BY 
    e.Id, e.Month DESC 

Ausgang ist:

+----+-------+--------+ 
| Id | Month | Salary | 
+----+-------+--------+ 
| 1 |  3 |  90 | 
| 1 |  2 |  50 | 
| 1 |  1 |  20 | 
| 2 |  1 |  20 | 
| 3 |  3 | 100 | 
| 3 |  2 |  40 | 
+----+-------+--------+ 
+0

Ja, das sollte auch funktionieren. –

+0

@ DL Danke für dein Antworten. Aber keiner deiner Codes funktioniert ... –

2

Versuchen Sie folgendes:

SELECT t1.id, t1.month, 
    (SELECT SUM(salary) 
     FROM employee t2 
     WHERE t1.id = t2.id 
     AND t1.month >= t2.month 
     AND t1.month - t2.month < 3) AS salary 
    FROM (
    SELECT * FROM employee p 
    WHERE month <> (select MAX(month) 
     FROM employee c where c.id = p.id)) t1 
ORDER BY id, month desc; 

Ausgang ist:

+------+-------+--------+ 
| id | month | salary | 
+------+-------+--------+ 
| 1 |  3 |  90 | 
| 1 |  2 |  50 | 
| 1 |  1 |  20 | 
| 2 |  1 |  20 | 
| 3 |  3 | 100 | 
| 3 |  2 |  40 | 
+------+-------+--------+ 

Das Problem, das Sie hatten, war, dass Sie nur den letzten Monat aller Mitarbeiter löschten. Was ich glaube, dass Sie wollten, war, den letzten Monat, der für jeden Angestellten vorhanden ist, zu löschen, selbst wenn dieser letzte Monat mehrere Monate zurück war. Diese Lösung erstellt eine abgeleitete Tabelle, in der der letzte Monat für jeden Mitarbeiter fehlt und diese anstelle Ihrer Tabelle t1 employee verwendet.

+0

Aktualisiert, um die Summe auf 3 Monate zu begrenzen. –

+0

Es funktioniert diesmal! Ihre Antwort macht mir mehr Sinn ... –

2

nur um die kumulative Summe für die letzten 3 Monate, ohne den letzten Monat pro-ID erhalten Sie

SELECT t1.Id, t1.Month, SUM(t2.Salary) 
FROM Employee t1 
JOIN Employee t2 ON t1.Id = t2.Id AND t1.Month - t2.Month <= 2 AND t1.Month - t2.Month >= 0 
JOIN (SELECT id, MAX(month) as max_mth from Employee GROUP BY id) tmax on tmax.id=t1.id AND tmax.max_mth<>t1.month 
GROUP BY t1.Id, t1.Month 
ORDER BY t1.Id, t1.Month DESC; 
+0

Netter Job, der die volle Frage einschließlich des Teils ungefähr 3 Monate liest. –

+0

Vielen Dank für Ihre Hilfe. Könntest du ein bisschen mehr erklären - warum funktioniert mein Originalcode nicht? Ich habe noch nie __AND__ in einer __JOIN__-Klausel verwendet - nicht sicher, ob es eine Referenzseite gibt? –

+0

@YunZhou Ich glaube, das zugrunde liegende Problem ist Ihre Zeile "GROUP BY t1.Id" nicht wirklich etwas tun, weil es ein Attribut außerhalb der verschachtelten Unterabfrage definiert ist. Es wird jedoch kein Fehler ausgegeben, da t1.id für die angegebene Unterabfrage konstant ist. –