3

2つの列が固定されている2つのテーブルがあります。一部の列は同一であり、一部は新しいものです。列は動的です。

コードレベルでそれを行う必要があり、ループして条件を付けようとしています

私が欲しいのは、条件に従ってレポートを生成することです。

  • table1 と table2 のすべての列が存在する必要があります。
  • 列が共通で値がある場合は、他のテーブルの同一の行に追加する必要があります。
  • 1 つのテーブルに存在し、他のテーブルには存在しない行がある場合は、それを含める必要があります。

サンプルデータ

表1

ID  | NAME | P1  | P2  | P3 
 ----------------------------
  1  | A1   | 1   |  2 | 3.3
  2  | A2   | 4.4 |  5 |  6

表 2

  ID  | NAME | P1 | P2  | P4 
 ---------------------------
  1  | A1   | 10  | 11  |  12
  2  | A2   | 12  | 14  |  15
  3  | A3   | 16  | 17  |  18

期待される出力:

 ID  | NAME | P1   |  P2  | P3  | P4
 ---------------------------------
  1  | A1   | 11   |  13  | 3.3 | 12
  2  | A2   | 16.4 |  19  |  6  | 15
  3  | A3   | 16   |  17  | null| 18

現在までの進捗:

最初に、これらの 2 つのテーブルを table1 にマージしました table1.Merge(table2)

次に、それをグループ化しようとしています

var query = from row in table1.AsEnumerable()
                        group row by new
                        {
                            ID = row.Field<int>("ID"),
                            Name = row.Field<string>("Name")
                        }
                            into grp
                            select new
                            {
                                ID = grp.Key.ID,
                                Name = grp.Key.Name,
                                Phase1 = grp.Sum(r => r.Field<decimal>("P1"))
                            };

このコードを変更してデータテーブルを取得しました。添付の cs ファイルを参照してください。
これは機能していますが、列の数は動的であるため、他の列についても繰り返して、1 つの列が追加されるこれらすべての小さなテーブルを結合する必要があると思います。

これらの小さなテーブルをすべてマージするにはどうすればよいですか?

私はここで道に迷っています。他の方法はありますか。バカみたいな感じ。

どんな助けでも大歓迎です。

添付ファイル:


http://dl.dropbox.com/u/26252340/Program.cs

4

3 に答える 3

2

完全外部結合の実装を使用したい。以下のようなもの。

あなたがこれを自分で試すことができるように、いくつかのセットアップ:

DataTable t1 = new DataTable();
t1.Columns.Add("ID", typeof(int));
t1.Columns.Add("Name", typeof(string));
t1.Columns.Add("P1", typeof(double));
t1.Columns.Add("P2", typeof(double));
t1.Columns.Add("P3", typeof(double));

DataRow dr1 = t1.NewRow();
dr1["ID"] = 1;
dr1["Name"] = "A1";
dr1["P1"] = 1;
dr1["P2"] = 2;
dr1["P3"] = 3.3;
t1.Rows.Add(dr1);
DataRow dr2 = t1.NewRow();
dr2["ID"] = 2;
dr2["Name"] = "A2";
dr2["P1"] = 4.4;
dr2["P2"] = 5;
dr2["P3"] = 6;
t1.Rows.Add(dr2);

DataTable t2 = new DataTable();
t2.Columns.Add("ID", typeof(int));
t2.Columns.Add("Name", typeof(string));
t2.Columns.Add("P1", typeof(double));
t2.Columns.Add("P2", typeof(double));
t2.Columns.Add("P4", typeof(double));

DataRow dr3 = t2.NewRow();
dr3["ID"] = 1;
dr3["Name"] = "A1";
dr3["P1"] = 10;
dr3["P2"] = 11;
dr3["P4"] = 12;
t2.Rows.Add(dr3);
DataRow dr4 = t2.NewRow();
dr4["ID"] = 2;
dr4["Name"] = "A2";
dr4["P1"] = 12;
dr4["P2"] = 14;
dr4["P4"] = 15;
t2.Rows.Add(dr4);
DataRow dr5 = t2.NewRow();
dr5["ID"] = 3;
dr5["Name"] = "A3";
dr5["P1"] = 16;
dr5["P2"] = 17;
dr5["P4"] = 18;
t2.Rows.Add(dr5);

クエリは次のようになります。

var ids = (from r1 in t1.AsEnumerable() select new { ID = r1["ID"], Name = r1["Name"] }).Union(
                    from r2 in t2.AsEnumerable() select new { ID = r2["ID"], Name = r2["Name"] });
var query = from id in ids
            join r1 in t1.AsEnumerable() on id equals new { ID = r1["ID"], Name = r1["Name"] } into left
            from r1 in left.DefaultIfEmpty()
            join r2 in t2.AsEnumerable() on id equals new { ID = r2["ID"], Name = r2["Name"] } into right
            from r2 in right.DefaultIfEmpty()    
            select new
            {
                ID = (r1 == null) ? r2["ID"] : r1["ID"],
                Name = (r1 == null) ? r2["Name"] : r1["Name"],
                P1 = (r1 == null) ? r2["P1"] : (r2["P1"] == null) ? r1["P1"] : (double)r1["P1"] + (double)r2["P1"],
                P2 = (r1 == null) ? r2["P2"] : (r2["P2"] == null) ? r1["P2"] : (double)r1["P2"] + (double)r2["P2"],
                P3 = (r1 == null) ? null : r1["P3"],
                P4 = (r2 == null) ? null : r2["P4"]
            };
于 2012-05-10T18:29:15.360 に答える
1

これで解決しました

table1.Merge(table2, true, MissingSchemaAction.Add);
finalTable = table1.Clone();
finalTable.PrimaryKey = new DataColumn[] { finalTable.Columns["ID"], finalTable.Columns["Name"] };
List<string> columnNames = new List<string>();
for (int colIndex = 2; colIndex < finalTable.Columns.Count; colIndex++)
{
columnNames.Add(finalTable.Columns[colIndex].ColumnName);
}
foreach (string cols in columnNames)
{
var temTable = new DataTable();
temTable.Columns.Add("ID", typeof(int));
temTable.Columns.Add("Name", typeof(string));
temTable.Columns.Add(cols, typeof(decimal));

(from row in table1.AsEnumerable()
group row by new { ID = row.Field<int>("ID"), Team = row.Field<string>("Team") } into grp
orderby grp.Key.ID
select new
{
ID = grp.Key.ID,
Name = grp.Key.Team,
cols = grp.Sum(r =>  r.Field<decimal?>(cols)),
})
.Aggregate(temTable, (dt, r) => { dt.Rows.Add(r.ID, r.Team, r.cols); return dt; });

finalTable.Merge(temTable, false, MissingSchemaAction.Ignore);
}
于 2012-05-11T03:20:47.650 に答える
1

列は動的であるため、動的プロパティを持つオブジェクトを返す必要があります。ExpandoObjectでこれを行うことができます。

次のコードは多くの点で醜いです - 私はそれを手放す前に大規模なリファクタリングを行います - しかし、それは仕事を成し遂げ、あなたが望むものを達成するのを助けるかもしれません.
(他の linq 構文を使用して申し訳ありません。)

var query = table1.AsEnumerable()
    .GroupBy(row => new
                    {
                        ID = row.Field<int>("ID"),
                        Name = row.Field<string>("Name")
                    })
    .Select(grp =>
    {
        dynamic result = new ExpandoObject();
        var dict = result as IDictionary<string, object>;
        result.ID = grp.Key.ID;
        result.Name = grp.Key.Name;
        foreach (DataRow row in grp)
        {
            foreach (DataColumn column in table1.Columns)
            {
                string columnName = column.ColumnName;
                if (columnName.Equals("ID") || columnName.Equals("Name"))
                    continue;
                //else
                if (!dict.Keys.Contains(columnName))
                    dict[columnName] = row[columnName];
                else
                {
                    if (row[columnName] is System.DBNull)
                        continue;
                    if (dict[columnName] is System.DBNull)
                    {
                        dict[columnName] = row[columnName];
                        continue;
                    }
                    //else
                    dict[columnName] = (decimal)dict[columnName] + (decimal)row[columnName];
                }
            }
        }
        return result;
    });
于 2012-05-10T22:49:38.390 に答える