2012-04-19 13 views
7

Mam tabeli jak to w projektanta raportu:SQL Server 2008 Reporting: Suma Max grupy

Category:  1  2  3  4 Total 
Max Amount:  x  y  z  c  ? 

Muszę dostać łącznie Max Kwota, ale wyrażenia nie pozwoli mi wziąć suma (Maks (kwota)), a suma dodania jest wyłączona dla tej komórki.

Wiersz maksymalnej kwoty to wyrażenie, które przyjmuje maksimum każdej kategorii. Dane źródłowe mają powtarzające się wartości, więc po prostu biorę maksimum. Na przykład:

Category Amount 
    1   4.6 
    1   4.6 
    1   4.6 
    2   5 
    3   4 

Pozostałe kolumny w tabeli są różne, ale kwota będzie taka sama, więc mogę nie tylko wybrać różne wartości.

+0

Jaka wersja SQL używasz? – Arion

+0

Używam 2008 – richsoni

Odpowiedz

9

Może coś takiego:

SELECT 
    SUM(t1.maxAmout) 
FROM 
(
    SELECT 
     MAX(t.Amout) AS maxAmout, 
     t.Category 
    FROM 
     yourTable AS t 
    GROUP BY 
     t.Category 
) AS t1 

Można również zrobić to w ten sposób. Jeśli używasz serwera sql 2005+:

SELECT 
    pvt.[1], 
    pvt.[2], 
    pvt.[3], 
    (
     pvt.[1]+ 
     pvt.[2]+ 
     pvt.[3] 
    ) AS Total 
FROM 
(
    SELECT 
     t.Category, 
     t.Amout 
    FROM 
     yourTable AS t 
) AS SourceTable 
PIVOT 
(
    MAX(Amout) 
    FOR Category IN([1],[2],[3]) 
) AS pvt 

EDIT

jeśli masz 1000 kategorie. Wtedy najlepszym rozwiązaniem byłoby dynamiczne przestawienie. Więc tak:

dane testowe

CREATE TABLE #T 
    (
     Category INT, 
     Amout FLOAT 
    ) 

INSERT INTO #T 
VALUES 
    (1,4.6), 
    (1,4.6), 
    (1,4.6), 
    (2,5), 
    (3,4) 

unikalne nazwy kolumn

DECLARE @cols VARCHAR(MAX) 
DECLARE @colsTotal VARCHAR(MAX) 
;WITH CTE 
AS 
(
    SELECT 
     ROW_NUMBER() OVER(PARTITION BY t.Category ORDER BY t.Amout) AS RowNbr, 
     t.* 
    FROM 
     #T AS t 
) 
SELECT @cols = COALESCE(@cols + ','+QUOTENAME(Category), 
        QUOTENAME(Category)), 
     @colsTotal=COALESCE(@colsTotal + '+ISNULL('+QUOTENAME(Category)+',0)', 
        'ISNULL('+QUOTENAME(Category)+',0)') 
FROM 
    CTE 
WHERE 
    CTE.RowNbr=1 
ORDER BY 
    Category 

Dynamiczny pivot

DECLARE @query NVARCHAR(4000)= 
N'SELECT 
    '[email protected]+', 
    (
     '[email protected]+' 
    ) AS Total 
FROM 
(
    SELECT 
     t.Category, 
     t.Amout 
    FROM 
     #T AS t 
) AS SourceTable 
PIVOT 
(
    MAX(Amout) 
    FOR Category IN('[email protected]+') 
) AS pvt' 

EXECUTE(@query) 
+0

co, jeśli istnieje 1000 kategorii? po prostu ciekawy, czy to jest najlepsze rozwiązanie: – dansasu11

+0

@paabobo: jeśli istnieje 1000 kategorii, to nadal robiłbym pivot. Ale w tym przypadku dynamiczny czop. Jeśli jest to najlepsze rozwiązanie, czy nie. Wszystko zależy od schematu bazy danych. Ale na plusie jest to, że musisz tylko grupować według nich. To musi być imadło wydajnościowe znacznie szybciej. Myślę, że w tym przypadku czop może być pozytywny dla wykonania. – Arion

+0

@rsoni: Pamiętaj, aby poprzeć odpowiedź, którą uważasz za dobrą. To daje nam uczucie ciepła: P – Arion

2
WITH 
    aggregate 
AS 
(
    SELECT 
    category, 
    MAX(amount) AS max_amount 
    FROM 
    yourTable 
    GROUP BY 
    category 
) 
SELECT 
    MAX(CASE WHEN category = 1 THEN max_amount ELSE NULL END) AS [1], 
    MAX(CASE WHEN category = 2 THEN max_amount ELSE NULL END) AS [2], 
    MAX(CASE WHEN category = 3 THEN max_amount ELSE NULL END) AS [3], 
    MAX(CASE WHEN category = 4 THEN max_amount ELSE NULL END) AS [4], 
    SUM(max_amount)            AS [total] 
FROM 
    aggregate 
0

Następujące zwraca pojedynczą wartość:

SELECT DISTINCT SUM(MAX(Amount)) OVER() 
FROM atable 
GROUP BY Category 

Można to wykorzystać jako podzapytania obliczania wartości kolumny Total.

Alternatywnie TOP (1) może być stosowany zamiast DISTINCT (nie wiem dlaczego nie mogę myśleć o tym wcześniej):

SELECT TOP (1) SUM(MAX(Amount)) OVER() 
FROM atable 
GROUP BY Category 
Powiązane problemy