В зависимости от того, что вы делаете, в некоторых случаях вы можете создать запрос или подготовленный оператор, чтобы сделать это за вас. Обычно они суммируют фиксированный набор известных столбцов. В этом случае мы не знаем, сколько столбцов даты будет или что они есть. Таким образом, мы можем сделать это в коде.
Я использовал Access вместо mySQL, но концепция такая же. Я также сделал это более сложным, регистрируя посещаемость по классу, которые не встречаются каждый день. Исходное данные:
я не буду использовать имя класса в результатах, это делает дисплей слишком широко.
Dim sql = <sql>
((Use your own SQL obviously))
</sql>.Value
Dim dtTemp As New DataTable
' get the data
Using dbcon As OleDbConnection = GetACEConnection(),
cmd As New OleDbCommand(sql, dbcon)
dbcon.Open()
Using da As New OleDbDataAdapter(cmd)
da.Fill(dtTemp)
End Using
End Using
' unique list of "date" columns in the result set
' ORDERBY Date is in the SQL
Dim colNames = dtTemp.AsEnumerable().
Select(Function(s) DateTime.Parse(s.Item("Date").ToString).
ToString("MM/dd/yyyy")).
Distinct.ToList()
' unique list of students
Dim Students = dtTemp.AsEnumerable().Select(Function(q) q.Item("Name")).
Distinct.ToList()
' the final table to use with the DGV
Dim dt As New DataTable
Dim colName As String
' add the name and class code designation columns
dt.Columns.Add(New DataColumn(dtTemp.Columns(0).ColumnName, GetType(String)))
dt.Columns.Add(New DataColumn(dtTemp.Columns(1).ColumnName, GetType(String)))
' add a "MM/dd/yyyy" text column for each possible class day
For n As Int32 = 0 To colNames.ToArray.Count - 1
colName = DateTime.Parse(colNames(n).ToString).ToString("MM/dd/yyyy")
dt.Columns.Add(New DataColumn(colName, GetType(String)))
Next
Dim newRow As DataRow
' loop thru all students
For Each s In Students
' the student-class dataset
Dim drs As DataRow() = dtTemp.Select(String.Format("Name = '{0}'", s.ToString)).
OrderBy(Function(o) o.Item("ClassCode")).ToArray
' create list of classes for this student
Dim classes = drs.AsEnumerable.
Select(Function(q) q.Item(1).ToString).Distinct.ToArray
For Each classcode As String In classes
' filter the drs results to the current class
Dim datestat As DataRow() = drs.AsEnumerable.
Where(Function(q) q.Item(1).ToString = classcode).ToArray
' create new row, copy the data from drs.Rows to dt.columns
newRow = dt.NewRow
newRow.Item(0) = s
newRow.Item(1) = classcode
' NOTE since not all students will have a class everyday, some
' "status" cells will be dbNull!
For Each statRow In datestat
Dim cname As String = DateTime.Parse(statRow.Item("Date").
ToString()).ToString("MM/dd/yyyy")
newRow.Item(cname) = statRow.Item("Status")
Next
dt.Rows.Add(newRow)
Next
Next
dgv.AutoGenerateColumns = True
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.ColumnHeader)
dgv.DataSource = dt
Оно не совсем так сложно, как это может выглядеть.
- Получить мастер набора данных для работы на
- Получить список уникальных имен студентов
- Имена столбцов для использования приходит из запроса Linq для извлечения уникальных дат класса в таблице данных
- Создать новый
DataTable
.
- После
StudentName
и ClassCode
петли добавляет один столбец для каждой даты, что соответствует любому класса. Имя столбца/текст заголовка поступает из только что созданного списка/массива ColNames
.
С DataTable назначения создан, вы можете начать копирование данных на него. Опять же, вместо объектов вы использовали бы объект MySQL...
, но они работают одинаково.
- Loop через все студент в списке студентов
- Для каждого извлечь список всех классов, которые они посещали из основных данных набора
- Loop через эти классы
- Извлечение строки для текущего класса из набора данных Student-Class
- Создайте новый
DataRow
с использованием итерационных часов Student и Class для первых двух столбцов.
- Преобразование каждого значения DateTime в текущий набор данных Student-Class в тот же формат, который используется для создания столбцов результатов (
cname
).
- использовать его, чтобы скопировать их статус:
newRow.Item(cname) = statRow.Item("Status")
в новой строке
- Так как классы не делаете встречаться каждый день, некоторые клетки будут пустыми (
DbNull
)
- Добавить новую строку в финал DataTable
Это было бы проще без отчетности по классам и просто сообщить о статусе на весь день. Результат:
наиболее запутанная часть с использованием датой данных в одном DataTable в качестве имени столбца в другом и зачистках времени части.
Это всего лишь первый проход, поэтому его можно скорее уточнить. Некоторая обработка может быть выполнена в SQL; метод DateTime.Parse
для преобразования данных DateTime
в строку в том же формате (удалить Time и т. д.) может быть его собственной процедурой. Я бы также использовал формат двухзначного года, чтобы заголовки немного были более узкими.
Измените свой вопрос, чтобы включить код, с которым вы пытались выполнить эту работу. – Blackwood