2015-01-15 1 views
8

У меня в основном снимок экрана ниже моего макета.SSRS Как получить первое и последнее значения группы строк матрицы?

Мои столбцы матрицы - DCG1 и DCG2.

В конце Матрицы у меня есть Total Group, которая работает только для поиска. Но я хочу найти разницу между моим первым и последним значением группы. Я пробовал все от ReportItems! к значениям. Я не могу заставить SSRS распознавать эти значения.

Так что в основном на снимках экрана ниже. Экран 1 - матричная структура. У меня есть группа столбцов Test1, я хочу первое значение Test1 и последнее значение теста 1 и поместите это в поле «Красное».

На скриншоте 2 вы можете увидеть значения, которые я хочу сравнить. Группы таблиц называются такими же, как столбцы + группы. Так dcs1group/dcs2group

enter image description here

enter image description here

Хорошо вот DDL и DML для источника данных

http://pastebin.com/1ySN701D

Pastebin был удален. Почему, не уверен, что вот здесь.

 
IF EXISTS 
     (SELECT [name] 
     FROM tempdb.sys.tables 
     WHERE [name] LIKE '%tmpHoldingTable%') 
    BEGIN 
     DROP TABLE #tmpHoldingTable; 
    END; 


CREATE TABLE #tmpHoldingTable 
(
    dcs1 NVARCHAR (50), 
    dcs2 NVARCHAR (50), 
    Total DECIMAL (10, 2), 
    Test1 NVARCHAR (50) 
) 

INSERT INTO #tmpHoldingTable (dcs1, 
           dcs2, 
           Total, 
           Test1) 
VALUES ('Contract', 
     'Breach of Contract', 
     500.00, 
     '01/01/2013-12/31/2013'), 
     ('Contract', 
     'Breach of Contract', 
     300.00, 
     '01/01/2014-12/31/2014'), 
     ('Employment', 
     'Discrimination', 
     500.00, 
     '01/01/2013-12/31/2013'), 
     ('Employment', 
     'Discrimination', 
     300.00, 
     '01/01/2014-12/31/2014'), 
     ('Employment', 
     'Research', 
     500.00, 
     '01/01/2013-12/31/2013'), 
     ('Employment', 
     'Research', 
     300.00, 
     '01/01/2014-12/31/2014') 

SELECT * FROM #tmpHoldingTable; 
+1

Вы пытались использовать 'First (Fields! Yourfield.value,« yourgroup »)' и 'Last (Fields! Yourfield.value,« yourgroup »)' –

+0

@CoderofCode конечно же сделал! но как вы используете несколько групп? Потому что действительно важно иметь все 3 группы! dcs1/DCS2/test1. ReportItems! не работает по этой причине –

+0

@CoderofCode, который вы получаете в этом случае, - имеет параметр scope, который недействителен для функции aggrgate. –

ответ

7

Да, это возможно, но, как вы можете видеть, это немного сложно.

Чтобы сделать это более общий ответ, я создал свой собственный DataSet, с упрощенными колоннами, но более подробной информации:

select grp = 1, val = 100, dt = cast('01-jan-2015' as date) 
union all select grp = 1, val = 110, dt = cast('01-jan-2015' as date) 
union all select grp = 1, val = 200, dt = cast('02-jan-2015' as date) 
union all select grp = 1, val = 210, dt = cast('02-jan-2015' as date) 
union all select grp = 1, val = 300, dt = cast('03-jan-2015' as date) 
union all select grp = 1, val = 310, dt = cast('03-jan-2015' as date) 
union all select grp = 1, val = 400, dt = cast('04-jan-2015' as date) 
union all select grp = 1, val = 410, dt = cast('04-jan-2015' as date) 
union all select grp = 1, val = 500, dt = cast('05-jan-2015' as date) 
union all select grp = 1, val = 510, dt = cast('05-jan-2015' as date) 
union all select grp = 2, val = 220, dt = cast('02-jan-2015' as date) 
union all select grp = 2, val = 230, dt = cast('02-jan-2015' as date) 
union all select grp = 2, val = 320, dt = cast('03-jan-2015' as date) 
union all select grp = 2, val = 330, dt = cast('03-jan-2015' as date) 
union all select grp = 2, val = 420, dt = cast('04-jan-2015' as date) 
union all select grp = 2, val = 430, dt = cast('04-jan-2015' as date) 

enter image description here

Обратите внимание, что каждый GRP/дт комбинация имеет два значения и что grp 1 более длинный диапазон для dt чем grp 2.

Я создал простую матрицу, основанную на этом:

enter image description here

Поскольку вы используете SQL Server 2012, вы можете использовать функцию LookupSet, чтобы получить первые/последние значения для каждой группы строк.

Выражение в первой группы строк TextBox является:

=Code.SumLookup(
    LookupSet(
     First(Fields!dt.Value, "grp").ToString & Fields!grp.Value.ToString 
     , Fields!dt.Value.ToString & Fields!grp.Value.ToString 
     , Fields!val.Value 
     , "DataSet1" 
    ) 
) 

На основании моих данных выборки, это дает свои требуемые результаты:

enter image description here

Обратите внимание, что второй grp строка имеет более узкий диапазон, чем первый, но его первый/последний столбцы независимы для каждой группы, поэтому в каждом из них grp. Здесь происходит немало вещей.

Пользовательский код для агрегации LookUpSet результата

Выражение LookupSet обернут в Code.SumLookup пользовательской функции:

Function SumLookup(ByVal items As Object()) As Decimal 
    If items Is Nothing Then 
    Return Nothing 
    End If 

    Dim suma As Decimal = New Decimal() 
    suma = 0 

    For Each item As Object In items 
    suma += Convert.ToDecimal(item) 
    Next 

    Return suma 
End Function 

Это взято из ответа на this SO вопрос.

Предполагается, что каждая ячейка матрицы может быть суммой нескольких значений, поэтому ее необходимо суммировать. LookupSet возвращает массив значений, который агрегируется по Code.SumLookup.

Детали для LookupSet

Далее, LoopupSet выражения сама:

LookupSet(
     First(Fields!dt.Value, "grp").ToString & Fields!grp.Value.ToString 
     , Fields!dt.Value.ToString & Fields!grp.Value.ToString 
     , Fields!val.Value 
     , "DataSet1" 
    ) 

LookupSet принимает следующие параметры:

LookupSet(source_expression, destination_expression, result_expression, dataset) 

В нашем выражении, мы хотим получить все значения из DataSet1, которые соответствуют первым dt в текущем grp сфере.

Для source_expression я использую:

First(Fields!dt.Value, "grp").ToString & Fields!grp.Value.ToString 

Это получает первый DT в рамках ряда ("grp" это имя группы строк), затем добавляет это к текущему GRP. Это создает выражение, соответствующее аналогичному выражению при поиске в DataSet1.

т.е. destination_expression:

Fields!dt.Value.ToString & Fields!grp.Value.ToString 

Наконец, мы указываем, что мы хотим Fields!val.Value как result_expression и DataSet1 в качестве параметра dataset.

Все соответствующие Fields!val.Value значения в DataSet1 сконструированы в массиве на LookupSet, а затем агрегированы по Code.SumLookup.

выражение Обновление для последних значений

Выражение для Last TextBox практически одинакова; просто изменить First к Last:

=Code.SumLookup(
    LookupSet(
     Last(Fields!dt.Value, "grp").ToString & Fields!grp.Value.ToString 
     , Fields!dt.Value.ToString & Fields!grp.Value.ToString 
     , Fields!val.Value 
     , "DataSet1" 
    ) 
) 

Получить разницу

Наконец, чтобы получить разницу в них, просто вычесть одно выражение из другого в Разница TextBox, или даже ссылаться на ReportItems значения:

=ReportItems!Last.Value - ReportItems!First.Value 

Где Last и First - это имена текстовых полей.

Заключение

Очевидно, что вам необходимо будет обновить для вашего конкретного случая, но вы можете видеть, что это может быть сделано.

Стоит ли делать это в своем отчете? Вы можете видеть, что есть много шагов, и в целом было бы проще обратиться при создании DataSet. Но, если это не вариант, мы надеемся, что этот подход LookupSet полезен.

1

AFAIK это невозможно в SSRS. Поверь мне, я попробовал. К счастью, у вас есть источник данных SQL, поэтому я бы разрешил это требование там, где у вас есть (почти) неограниченные полномочия для формирования и управления данными.

Для примера я хотел бы заменить ваш окончательный выбор с:

; WITH CTE_Base AS ( SELECT * FROM #tmpHoldingTable ) , CTE_Test1 AS ( SELECT Test1 , ROW_NUMBER() OVER (ORDER BY Test1) AS Column_Number_Test1 FROM CTE_Base GROUP BY Test1 ) SELECT CTE_Base.* , CTE_Test1.Column_Number_Test1 , CASE WHEN CTE_Test1.Column_Number_Test1 = 1 THEN Total WHEN CTE_Test1.Column_Number_Test1 = (SELECT MAX (Column_Number_Test1) FROM CTE_Test1) THEN 0 - Total ELSE 0 END AS [Difference] FROM CTE_Base INNER JOIN CTE_Test1 ON CTE_Base.Test1 = CTE_Test1.Test1

Это добавляет столбец [Difference] с копией [Всего] за 1-й столбец и 0 - [Всего] за последний колонка.

Возможно, SQL был бы более эффективен, но, надеюсь, его простое использование в CTE проще.

Затем в конструкторе SSRS вы можете добавить столбец [Difference] вне группы столбцов [Test1] и дать ему сумму (по умолчанию).

Кстати, ваши тестовые данные кажутся немного упрощенными - он будет производить только 2 столбца, и все ячейки имеют значения. Но его замечательный вы опубликовали DDL & DML - он упростил расширение данных и кода и протестировал это.

+0

Майк - хорошо, что я надеюсь, что он может быть обработан через SSRS. Только два столбца не имеют значения, вы всегда связаны с первым и последним. Я надеялся, что какая-то шикарная функция inScope будет работать. Как вы заметили, набор данных упрощен.Я обычно делаю все так просто, как могу, и масштабирую его. Я уверен, что есть определенный способ справиться с этим через sql, однако реальный набор данных и окружающая среда намного сложнее. –

+0

Я тоже могу вспомнить ту надежду, которую я почувствовал, когда функции типа Агрегат/Область были добавлены в SSRS еще в 2005 году. Поскольку то я много раз пытался растянуть границы того, что они могут сделать - несчастная реальность такова, что они очень ограничены. –

 Смежные вопросы

  • Нет связанных вопросов^_^