Запрос динамических столбцов DataTable в VB.net с помощью LINQ

Вопрос или проблема

У меня та же проблема, что и здесь: https://stackoverflow.com/questions/35629519/vb-net-datatable-dynamic-columns-query-fields-with-linq/79040444

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

Есть ли кто-то, у кого есть идея?

Спасибо

Вот пример:

Dim dtGroup = From row In dt
              Group row By dateGroup = New With {
                                        Key .az = row.Field(Of String)("az")
                                   } Into Group
              Select New With {
                      Key .Company = dateGroup,
                          .SumImp = Group.Sum(Function(x) x.Field(Of Decimal)("imp")),
                          .SumCl = Group.Sum(Function(x) x.Field(Of Decimal)("cl")),
                          .AvgCpc = Group.Average(Function(x) x.Field(Of Decimal)("cpc")),
                          .AvgCost = Group.Average(Function(x) x.Field(Of Decimal)("cost")),
                          .Count = Group.Count()
                    }

Ответ или решение

Конечно! Ваша задача состоит в том, чтобы динамически обрабатывать данные из объекта DataTable и выполнять агрегационные операции, такие как сумма и среднее, для неизвестного количества столбцов. Мы можем создать решение на VB.NET с использованием LINQ, чтобы достичь этой цели.

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

Вот пример решения этой задачи:

Dim dt As DataTable = New DataTable()
' Заполните ваш DataTable dt. Например:
' dt.Columns.Add("az", GetType(String))
' dt.Columns.Add("imp", GetType(Decimal))
' dt.Columns.Add("cl", GetType(Decimal))
' dt.Columns.Add("cpc", GetType(Decimal))
' dt.Columns.Add("cost", GetType(Decimal))
' dt.Rows.Add(...)

' Получаем все имена столбцов, кроме столбца для группировки
Dim dynamicColumns = dt.Columns.Cast(Of DataColumn)().Where(Function(c) c.ColumnName <> "az").ToList()

' Создаем динамическую агрегацию
Dim dtGroup = From row In dt.AsEnumerable()
               Group row By dateGroup = row.Field(Of String)("az") Into Group
               Select New With {
                   .Company = dateGroup,
                   .SumValues = dynamicColumns.ToDictionary(Function(c) c.ColumnName, 
                       Function(c) Group.Sum(Function(x) x.Field(Of Decimal)(c.ColumnName))),
                   .AvgValues = dynamicColumns.ToDictionary(Function(c) c.ColumnName,
                       Function(c) Group.Average(Function(x) x.Field(Of Decimal)(c.ColumnName))),
                   .Count = Group.Count()
               }

' Пример обработки результатов
For Each item In dtGroup
    Console.WriteLine($"Company: {item.Company}, Count: {item.Count}")
    For Each column In dynamicColumns
        Console.WriteLine($"Column: {column.ColumnName}, Sum: {item.SumValues(column.ColumnName)}, Avg: {item.AvgValues(column.ColumnName)}")
    Next
Next

В этом решении:

  1. Мы извлекаем все динамические столбцы, исключая столбец для группировки ("az").
  2. Используем LINQ для группировки строк по значению столбца "az".
  3. Создаём словари SumValues и AvgValues, чтобы хранить суммы и средние значения для каждого динамического столбца.
  4. В конце выводим результаты на консоль.

Это решение эффективно обрабатывает динамическое количество столбцов в DataTable и позволяет вам выполнять агрегации, не зная заранее, сколько именно столбцов будет в таблице.

Если у вас остались вопросы или требуется дополнительная помощь, пожалуйста, дайте знать!

Оцените материал
Добавить комментарий

Капча загружается...