2012-04-19 2 views
7

У меня есть таблица, как это в дизайнере отчетов:SQL Server 2008 Reporting: Сумма Макс группы

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

Мне нужно, чтобы получить в общей сложности Max сумма, но выражения не позволит мне взять Sum (Макс. (Сумма)), а общая сумма для этой ячейки отключена.

Максимальное количество строк - это выражение, которое принимает максимум каждой категории. Исходные данные имеют повторяющиеся значения, поэтому я просто беру max. Например:

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

Другие столбцы в таблице различны, но сумма будет такой же, так что я могу не только выбирать различные значения.

+0

Какую версию SQL вы используете? – Arion

+0

Я использую 2008 – richsoni

ответ

9

Может быть что-то вроде этого:

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

Вы также можете сделать это следующим образом. Если вы используете 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

Если у вас есть 1000 категорий. Тогда оптимальным решением будет динамический стержень. Так как это:

Тестовые данные

CREATE TABLE #T 
    (
     Category INT, 
     Amout FLOAT 
    ) 

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

Уникальные имена столбцов

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 

Динамический шарнирные

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

Что делать, если есть 1000 категорий? просто любопытно, если это лучшее решение – dansasu11

+0

@paabobo: если есть 1000 категорий, все равно будет стержень. Но в этом случае динамический стержень. Если это лучшее решение или нет. Все зависит от схемы базы данных. Но на плюсе есть то, что вам нужно только группировать их. Это должно быть производительность тисков гораздо быстрее. Я думаю, что в этом случае стержень может быть положительным для производительности. – Arion

+0

@rsoni: Помните, чтобы поддержать ответ, который вы считаете хорошим. Это дает нам все теплое нечеткое чувство: 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

Следующие возвращает одно значение:

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

Вы могли бы использовать это в качестве подзапроса вычисления значения Total столбца.

В качестве альтернативы, TOP (1) может быть использован вместо DISTINCT (не знаю, почему я не мог думать об этом раньше):

SELECT TOP (1) SUM(MAX(Amount)) OVER() 
FROM atable 
GROUP BY Category 
Смежные вопросы