2012-08-16 4 views
5

Ich habe eine einfache Tabelle mit einigen Dummy-Daten Setup wie:T-SQL mit SUM für eine laufende Gesamt

|id|user|value| 
--------------- 
1 John 2 
2 Ted 1 
3 John 4 
4 Ted 2 

ich eine laufende Summe durch Ausführen der folgenden SQL (MSSQL 2008) wählen kann Anweisung:

SELECT a.id, a.user, a.value, SUM(b.value) AS total 
FROM table a INNER JOIN table b 
ON a.id >= b.id 
AND a.user = b.user 
GROUP BY a.id, a.user, a.value 
ORDER BY a.id 

Das wird mir geben Ergebnisse wie:

|id|user|value|total| 
--------------------- 
1 John 2  2 
3 John 4  6 
2 Ted 1  1 
4 Ted 2  3 

Jetzt ist es möglich, nur die letzten Zeilen für ea abrufen ch Benutzer? Also wäre das Ergebnis:

|id|user|value|total| 
--------------------- 
3 John 4  6 
4 Ted 2  3 

Gehe ich das richtig? irgendwelche Vorschläge oder ein neuer Weg zu folgen wäre großartig!

+3

Sind Sie nur am Endergebnis interessiert, oder benötigen Sie auch die laufende Summe? Speichern Sie diese laufende Summe bereits irgendwo oder verwenden Sie sie nur, um Ihr Endergebnis zu generieren? * [Ihr Endergebnis kann effizienter erstellt werden, ohne eine laufende Summe zu verwenden. Aber, wenn Sie bereits die laufende Summe irgendwo gespeichert haben, kann es aus anderen Gründen sicherlich verwendet werden.] * – MatBailie

+0

Sie haben Ihre akzeptierte Antwort zur Verbesserung der Leistung geschaltet, aber Sie haben auf meine obige Anfrage nicht geantwortet. Beachten Sie, dass Sie die Leistung verbessern können, indem Sie *** *** mit der Methode "Laufende Summe" verwenden. Wäre das für Sie interessant oder benötigen Sie auch alle Ergebnisse in der laufenden Summe *? – MatBailie

+0

Hallo Leute, ich arbeitete fleißig und vermisste deinen Kommentar. Ich bin erst nach dem Total und dem damit verbundenen Benutzer, also ja ich bin an verbesserter Leistung interessiert. – luke2012

Antwort

5

versuchen Sie dies:

;with cte as 
    (SELECT a.id, a.[user], a.value, SUM(b.value) AS total 
    FROM users a INNER JOIN users b 
    ON a.id >= b.id 
    AND a.[user] = b.[user] 
    GROUP BY a.id, a.[user], a.value 
    ), 
cte1 as (select *,ROW_NUMBER() over (partition by [user] 
         order by total desc) as row_num 
     from cte) 
select id,[user],value,total from cte1 where row_num=1 

SQL Fiddle Demo

+0

Danke, das funktioniert auch mit besserer Leistung! – luke2012

+0

@Joe G Joseph, es sieht so aus, als wäre der Link zur SQL Fiddle kaputt. – rstackhouse

+0

Dies funktioniert auch nicht auf SQL Server 2008. – rstackhouse

1

Add wo Anweisung:

select * from 
(
your select statement 
) t 

where t.id in (select max(id) from table group by user) 

auch können Sie diese Abfrage verwenden:

SELECT a.id, a.user, a.value, 

(select max(b.value) from table b where b.user=a.user) AS total 

FROM table a 

where a.id in (select max(id) from table group by user) 

ORDER BY a.id 
+0

Vielen Dank, funktioniert super! – luke2012

0

Hinzufügen einer rechten anschließen würde eine bessere Leistung als wählen verschachtelt.

Oder noch einfacher:

SELECT MAX(id), [user], MAX(value), SUM(value) 
FROM table 
GROUP BY [user] 
+0

Aber max (id) und max (Wert) können aus verschiedenen ursprünglichen Tabellenzeilen stammen. – valex

+0

-1: Dies ist ein vereinfachter Ansatz, der einfach nicht richtig funktioniert. Sie können nicht davon ausgehen, dass MAX (ID) und MAX (Wert) Ergebnisse aus derselben Eingabezeile ergeben. – MatBailie

+0

Sie haben recht, wurde mir nach dem Posten klar. Dennoch würde eine intelligente Verknüpfung mit Rechten besser funktionieren als eine geschachtelte Auswahl. –

9

Keine beitreten erforderlich ist, können Sie die Abfrage auf diese Weise beschleunigen:

select id, [user], value, total 
from 
(
    select id, [user], value, 
    row_number() over (partition by [user] order by id desc) rn, 
    sum(value) over (partition by [user]) total 
from users 
) a 
where rn = 1 
+3

+1: Völlig vermeidet den seltsamen Vorschlag der Verwendung einer laufenden Summe ... – MatBailie

+0

Dies kann weiter beschleunigt werden, indem explizit die zusätzlichen Argumente für die over-Klausel von "SUM OVER" angegeben werden – whytheq

0

Kompatibel ble mit SQL Server 2008 oder später

DECLARE @AnotherTbl TABLE 
    (
     id   INT 
     , somedate  DATE 
     , somevalue DECIMAL(18, 4) 
     , runningtotal DECIMAL(18, 4) 
    ) 

INSERT INTO @AnotherTbl 
    (
     id 
     , somedate 
     , somevalue 
     , runningtotal 
    ) 
SELECT LEDGER_ID 
     , LL.LEDGER_DocDate 
     , LL.LEDGER_Amount 
     , NULL 
FROM ACC_Ledger LL 
ORDER BY LL.LEDGER_DocDate 

DECLARE @RunningTotal DECIMAL(18, 4) 
SET @RunningTotal = 0 

UPDATE @AnotherTbl 
SET @RunningTotal=runningtotal = @RunningTotal + somevalue 
FROM @AnotherTbl 

SELECT * 
FROM @AnotherTbl