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

列数が不明なFlatternの子/親データ

    これに何日も取り組んだ後、私はこの問題を自分で解決することができました。私がしたことは次のとおりでした;

    私の元の子クラスでは、MemberCodeとElementCodeは、基本的に列名が何であるかを示す一意のキーを作成します。そこで、これをさらに一歩進めて、「Column_Name」を追加しました。

    public class Child
    {
            public int MemberCode { get; set; }   //Composite key
            public int ElementCode { get; set; }  //Composite key
            public string Column_Name { get; set; }  //Unique.  Alternative Key
            public Object Data { get; set; }
    }
    

    これは明らかに私のデータベーステーブルにも反映されていました。

    データを抽出するための私のSQLは次のようになりました;

    select  p.UniqueID, p.LoadTime, p.reference, c.MemberCode, c.ElementCode , c.column_name, c.Data 
    from parent as p, child as c
    where p.UniqueID = c.UniqueID 
    //aditional filter criteria
    ORDER BY p.UniqueID, MemberCode, ElementCode
    

    レコードを後で処理するために正しい順序にするためには、UniqueIDによる最初の順序付けが重要です。

    dynamicを使用します およびExpandoObject() データを保存します。

    そのため、結果を繰り返し処理して、SQLの結果を次のようにこの構造に変換します。

    List<dynamic> allRecords = new List<dynamic>();  //A list of all my records
    List<dynamic> singleRecord = null;  //A list representing just a single record
    
    bool first = true;   //Needed for execution of the first iteration only
    int lastId = 0;      //id of the last unique record
    
    foreach (DataRow row in args.GetDataSet.Tables[0].Rows)
    {
        int newID = Convert.ToInt32(row["UniqueID"]);  //get the current record unique id   
    
        if (newID != lastId)  //If new record then get header/parent information
        {
            if (!first)
                allRecords.Add(singleRecord);   //store the last record
            else
                first = false;
    
            //new object
            singleRecord = new List<dynamic>();
    
            //get parent information and store it
            dynamic head = new ExpandoObject();
            head.Column_name = "UniqueID";
            head.UDS_Data = row["UniqueID"].ToString();
            singleRecord.Add(head);
    
            head = new ExpandoObject();
            head.Column_name = "LoadTime";
            head.UDS_Data = row["LoadTime"].ToString();
            singleRecord.Add(head);
    
            head = new ExpandoObject();
            head.Column_name = "reference";
            head.UDS_Data = row["reference"].ToString();
            singleRecord.Add(head);                    
        }
    
        //get child information and store it.  One row at a time
        dynamic record = new ExpandoObject();
    
        record.Column_name = row["column_name"].ToString();
        record.UDS_Data = row["data"].ToString();
        singleRecord.Add(record);
    
        lastId = newID;   //store the last id
    }
    allRecords.Add(singleRecord);  //stores the last complete record
    

    次に、必要なフラットな方法で情報を動的に保存します。

    次の問題は、使用したいObjectListViewでした。これはそのような動的タイプを受け入れることができませんでした。

    そのため、必要に応じて情報をコード内に保存しましたが、それでも必要な情報を表示できませんでした。

    解決策は、ObjectListViewのバリアントを使用することでした。 DataListViewとして知られています 。これは事実上同じコントロールですが、データにバインドできます。別の方法としてDatagridViewを使用することもできますが、他の理由でObjectListViewに固執したかったのです。

    そのため、動的データをデータソースに変換する必要がありました。これは次のように行いました;

    DataTable dt = new DataTable();            
    foreach (dynamic record in allRecords)
    {
        DataRow dr = dt.NewRow();
        foreach (dynamic item in record)
        {
            var prop = (IDictionary<String, Object>)item;
            if (!dt.Columns.Contains(prop["Column_name"].ToString()))
            {
                dt.Columns.Add(new DataColumn(prop["Column_name"].ToString()));
            }
    
            dr[prop["Column_name"].ToString()] = prop["UDS_Data"];
        }
        dt.Rows.Add(dr);
    }
    

    次に、データソースをDataListViewに割り当て、列を生成するだけで、動的データが抽出され、フラット化され、必要な方法で表示されます。




    1. MariaDB ROUND()とTRUNCATE()

    2. MySQLの階層データから深度ベースのツリーを生成する(CTEなし)

    3. Oracleで日付から日を取得する2つの方法

    4. 'Check'ステートメントを使用してmysqlのフィールド値を検証するにはどうすればよいですか?