sql >> Databáze >  >> RDS >> Mysql

Sloučit styl Pivot tabulky pro zobrazení Datagrid

V závislosti na tom, co děláte, můžete v některých případech vytvořit dotaz nebo připravený příkaz, který to udělá za vás. Obvykle se jedná o shrnutí pevné sady známých sloupců. V tomto případě nevíme, kolik sloupců s datem bude nebo jaké to jsou. Takže to můžeme udělat v kódu.

Místo mySQL jsem použil Access, ale koncept je stejný. Také jsem to zkomplikoval logováním docházky podle tříd, které se nescházejí každý den. Počáteční data:

Ve výsledcích nebudu používat název třídy, protože to dělá zobrazení příliš široké.

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

Není to tak složité, jak to může vypadat.

  1. Získejte hlavní datovou sadu, na které můžete pracovat
  2. Získejte seznam jedinečných jmen studentů
  3. Názvy sloupců, které se mají použít, pocházejí z dotazu linq k extrakci jedinečných dat třídy v datové tabulce
  4. Vytvořte nový DataTable za výsledky.
    • Za StudentName a ClassCode smyčka přidá jeden sloupec pro každé datum, které jakékoli třída schází. Názvy sloupců/text záhlaví pochází z ColNames právě vytvořený seznam/pole.

Po vytvoření cílové tabulky DataTable do ní můžete začít kopírovat data. Opět místo OleDB... objekty, které byste použili MySQL... objekt, ale fungují stejně.

  1. Procházet všemi studenty v seznamu studentů
  2. Pro každou z nich extrahujte seznam všech kurzů, které navštěvovali, ze souboru kmenových dat
  3. Projděte tyto třídy
  4. Extrahujte řádky pro aktuální třídu z datové sady Student-Class
  5. Vytvořte nový DataRow pomocí iteračních proměnných Student a Class pro první 2 sloupce.
  6. Převeďte každou hodnotu DateTime v aktuální datové sadě Student-Class do stejného formátu, jaký se používá k vytvoření sloupců výsledků (cname ).
    • použijte jej ke zkopírování jejich stavu:newRow.Item(cname) = statRow.Item("Status") do nového řádku
    • Vzhledem k tomu, že se třídy nescházejí každý den, budou některé buňky prázdné (DbNull )
  7. Přidejte nový řádek do konečné datové tabulky

Bylo by to jednodušší bez hlášení Podle třídy a pouze hlásit stav za celý den. Výsledek:

Nejvíce matoucí je použití datových dat v jedné datové tabulce jako sloupec name v jiném a odstraněním časové části.

To je jen první průchod, takže to může být pravděpodobně upřesněno. Některé zpracování může být možné provést v SQL; DateTime.Parse metoda pro převod DateTime data do řetězce ve stejném formátu (odstranění času atd.) může být vlastní procedurou. Také bych použil dvouznakový formát roku, aby se záhlaví trochu zúžila.




  1. Funkce načítání jQuery-Ajax s třídami a funkcemi PHP

  2. Jak vytvoříte verzi schématu databáze?

  3. Co je databáze? Definice, typy a komponenty

  4. Codeigniter ActiveRecord:připojit zpětné zaškrtnutí