sql >> データベース >  >> RDS >> Mysql

Datagridviewのテーブルピボットスタイルをフラット化する

    何をしているかによっては、クエリまたはプリペアドステートメントを作成してこれを行うことができる場合があります。これらは通常、既知の列の固定セットを要約するためのものです。この場合、日付列がいくつあるか、またはそれらが何であるかはわかりません。したがって、コードでそれを行うことができます。

    mySQLの代わりにAccessを使用しましたが、概念は同じです。また、毎日会わないクラスごとの出席を記録することで、より複雑にしました。開始データ:

    結果にクラス名を使用しないと、表示が広すぎます。

    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
    

    見た目ほど複雑ではありません。

    1. マスターデータセットを取得して作業する
    2. 一意の学生名のリストを取得する
    3. 使用する列名は、データテーブル内の一意のクラス日付を抽出するためのlinqクエリから取得されます
    4. 新しいDataTableを作成します 結果のために。
      • StudentNameの後 およびClassCode ループは、任意の日付ごとに1つの列を追加します クラスが出会う。列名/ヘッダーテキストはColNamesから取得されます 作成したばかりのリスト/配列。

    宛先のDataTableが作成されたら、そこへのデータのコピーを開始できます。繰り返しますが、OleDB...の代わりに MySQL...を使用するオブジェクト オブジェクトですが、同じように機能します。

    1. 生徒リストのすべての生徒をループします
    2. それぞれについて、マスターデータセットから参加したすべてのクラスのリストを抽出します
    3. これらのクラスをループします
    4. Student-Classデータセットから現在のクラスの行を抽出します
    5. 新しいDataRowを作成します 最初の2列にStudentとClassの反復変数を使用します。
    6. 現在のStudent-Classデータセットの各DateTime値を、結果列の作成に使用したのと同じ形式に変換します(cname )。
      • ステータスをコピーするために使用します:newRow.Item(cname) = statRow.Item("Status") 新しい行へ
      • クラスは毎日会わないため、一部のセルは空白になります(DbNull
    7. 新しい行を最終的なデータテーブルに追加します

    クラス別レポートがない方が簡単で、1日全体のステータスをレポートするだけです。結果:

    最も紛らわしいのは、日付データの使用です。 1つのデータテーブル内の列name 別の時間部分を取り除きます。

    これは最初のパスにすぎないため、改良できる可能性があります。一部の処理はSQLで実行できる場合があります。 DateTime.Parse DateTimeを変換するメソッド 同じ形式の文字列へのデータ(時刻の削除など)は、独自の手順である可能性があります。また、ヘッダーを少し狭くするために2文字の年形式を使用します。




    1. 高速テストのためにPostgreSQLを最適化する

    2. 数値を最も近い10に切り捨てるにはどうすればよいですか?

    3. 式をデータ型datetimeに変換する算術オーバーフローエラー。 (日時表示中..)

    4. mysqlの部分的な単語検索