Выполните группировку наборов результатов в коде, а не на уровне базы данных - PullRequest
3 голосов
/ 13 апреля 2010

Stackoverflowers,

У меня есть результат из запроса SQL в виде:

Category  Column2   Column3
A         2        3.50  
A         3        2  
B         3        2  
B         1        5  
...

Мне нужно сгруппировать набор результатов на основе столбца Category и суммировать значения для Column2 и Column3. Я должен сделать это в коде, потому что я не могу выполнить группирование в запросе SQL, который получает данные из-за сложности запроса (длинная история). Эти сгруппированные данные будут затем отображены в таблице.

У меня это работает для определенного набора значений в столбце Категория, но я бы хотел решение, которое обрабатывает любые возможные значения, которые появляются в столбце Категория.

Я знаю, что должен быть прямой, эффективный способ сделать это, но я не могу сейчас обернуть голову вокруг этого. Как бы вы этого достигли?

РЕДАКТИРОВАТЬ

Я попытался сгруппировать результат в SQL, используя точно такой же запрос на группировку, предложенный Томасом Левеском, и оба раза вся наша СУБД разбилась, пытаясь обработать запрос.

У меня сложилось впечатление, что Linq был недоступен до .NET 3.5. Это веб-приложение .NET 2.0, поэтому я не думал, что это вариант. Я ошибаюсь, думая об этом?

EDIT

Начинать вознаграждение, потому что я считаю, что это будет хорошей техникой для использования в наборе инструментов, независимо от того, откуда поступают разные наборы результатов. Я полагаю, что знание наиболее краткого способа группировки любых двух несколько похожих наборов данных в коде (без .NET LINQ) было бы полезно для большего числа людей, чем только для меня.

EDIT

Вот решение, которое я придумал в VB.NET на случай, если кому-то понадобится. Он использует ответ Пола Уильямса в качестве отправной точки. Я беру значения непосредственно из устройства чтения данных.

Public Class Accumulator
    Public sum1 As Integer
    Public sum2 As Decimal
End Class

If IReader.HasRows Then
    Dim grouping As New Dictionary(Of String, Accumulator)

    Do While IReader.Read
        Dim sum As New Accumulator

        If grouping.ContainsKey(IReader.GetString(0)) Then
            sum = grouping.Item(IReader.GetString(0))
        Else
            sum = New Accumulator
            grouping.Item(IReader.GetString(0)) = sum
        End If

        sum.sum1+= IReader.GetInt32(1)
        sum.sum2 += IReader.GetInt32(2)
    Loop

    For Each key As KeyValuePair(Of String, Accumulator) In grouping
        "DO WHAT YOU NEED TO DO WITH THE VALUES HERE"
    Next
End If

Ответы [ 4 ]

5 голосов
/ 13 апреля 2010

Я не могу выполнить группировку в запросе SQL, который получает данные из-за сложности запроса (длинный рассказ)

Ты уверен в этом? вам просто нужно поместить оператор SELECT ... GROUP BY ... вокруг вашего сложного запроса:

SELECT Category, SUM(Column2), SUM(Column3)
FROM ( /* your query here */ )
GROUP BY Category

В любом случае, если вы действительно хотите сделать это в коде, самый простой способ - использовать Linq. Предполагая, что результаты хранятся в списке объектов:

var groupedByCategory =
                    from r in results
                    group r by r.Category into g
                    select new
                    {
                        Category = g.Key,
                        SumOfColumn2 = g.Sum(x => x.Column2),
                        SumOfColumn3 = g.Sum(x => x.Column3)
                    };

UPDATE

Я попытался сгруппировать результат в SQL с использованием точно такой же группировки запрос, предложенный Томасом Левеском и оба раза вся наша СУБД разбилась пытается обработать запрос.

Э-э ... какую СУБД вы используете? просто чтобы убедиться, что я никогда не использую его случайно;)

У меня сложилось впечатление, что Линк был недоступен до .NET 3.5. это такое веб-приложение .NET 2.0, поэтому я не думаю, что это был вариант. Я ошибся Думая об этом?

Нет, вы правы. Linq поставляется с .NET 3.5 и недоступен в более ранних версиях.

Однако, если вы используете VS2008 для создания приложения для .NET 2.0, вас может заинтересовать LinqBridge: это альтернативная реализация стандартных операторов Linq, которая не зависит от .NET 3.5 , Вам просто нужен компилятор C # 3 (который поставляется с VS2008)

2 голосов
/ 26 апреля 2010

Вы можете создать словарь категорий для объекта, который будет содержать суммы. Например:

public class Accumulator
{
    public decimal SumColumn2;
    public decimal SumColumn3;
}

Dictionary<string, Accumulator> grouping = new Dictionary<string, Accumulator>;
DataTable dt = ... // this is the ungrouped DataTable
foreach (DataRow dr in dt.Rows)
{
    string category = dr["Category"];
    decimal col2 = dr["Column2"];
    decimal col3 = dr["Column3"];
    Accumulator sum = grouping[category];
    if (sum == null)
    {
        sum = new Accumulator();
        grouping[category] = sum;
    }
    sum.SumColumn2 += col2;
    sum.SumColumn3 += col3;
}

Отсюда вы можете разработать более общее решение, если это необходимо.

0 голосов
/ 03 мая 2010

Вы пытались отсортировать таблицу данных с помощью DefaultView? См. MSDN .

void SumDataTable() {
    MyDataTable.DefaultView.Sort = "ColumnName ASC";
    foreach( DataRowView drv in MyDataTable.DefaultView ) {
        MyDataRow dr = drv.Row as MyDataRow;    // get your DataRow type
        // results here, search in a list of custom summing classes, 
        // or use a Dictionary style approach
}

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

0 голосов
/ 26 апреля 2010

Определение группы «при любом изменении стоимости» Итак, есть переменная, которая хранит текущую и предыдущую категорию. Зацикливая свои результаты, сохраняйте текущую сумму и сбрасывайте при любом изменении значения категории. в конце цикла или перед следующим чтением установите значение prev для текущего значения. Таким образом, вам не нужно заранее знать, какие категории.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...