我有几个表(构建程序时确切的数字是未知的)看起来像这样(行和列的数量可能因表而异):
源数据存储在数据集中。现在我想生成一个新表,其中存储了所有id的所有数据(图片仅显示id 10和20的结果,但目标表应包含所有id的数据):
对此的等效SQLite语句如下所示:
SELECT * FROM Dataset
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=10
UNION
SELECT * FROM Dataset
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=20
...
之后将删除双id列,因此不必担心。现在的问题是如何将其转换为动态LINQ查询?
答案 0 :(得分:1)
有很多悬而未决的问题但也许这有助于解决它。由于表格已存储在DataSet
中,因此您可以使用Linq-To-DataSet
和Enumerable.GroupBy
按ID进行分组:
var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("Id"));
if(!idTables.Any()){ MessageBox.Show("No id-tables"); return; }
var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
.GroupBy(row => row.Field<int>("Id"))
.Select(grp => new { ID = grp.Key, Rows = grp });
foreach(var idGroup in idRowGroups)
{
Console.WriteLine("ID:{0} Rows:{1}"
, idGroup.ID
, String.Join(" | ", idGroup.Rows.Select(row => String.Join(",", row.ItemArray))));
}
示例数据:
var ds = new DataSet();
DataTable t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(1, 1);
t1.Rows.Add(2, 10);
t1.Rows.Add(3, 100);
t1.Rows.Add(4, 1000);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(4, 5);
t1.Rows.Add(5, 50);
t1.Rows.Add(7, 500);
t1.Rows.Add(3, 5997);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data1", typeof(int));
t1.Columns.Add("Data2", typeof(int));
t1.Rows.Add(1, 5, 0);
t1.Rows.Add(3, 7, 1);
t1.Rows.Add(5, 9, 11);
t1.Rows.Add(7, 11, 222);
ds.Tables.Add(t1);
输出:
ID:1 Rows:1,1 | 1,5,0
ID:2 Rows:2,10
ID:3 Rows:3,100 | 3,5997 | 3,7,1
ID:4 Rows:4,1000 | 4,5
ID:5 Rows:5,50 | 5,9,11
ID:7 Rows:7,500 | 7,11,222
答案 1 :(得分:0)
好吧,我终于做到了,但似乎太复杂了。如果有人能够帮助我改进解决方案,我非常欢迎。
DataSet dsResult = new DataSet();
var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("ID"));
if (!idTables.Any()) { MessageBox.Show("No id-tables"); return; }
var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
.GroupBy(row => row.Field<Int64>("ID"))
.Select(grp => new { ID = grp.Key, Rows = grp });
foreach (var idGroup in idRowGroups)
{
var liste = idGroup.Rows.ToList();
for (int i = 0; i < liste.Count; i++)
{
if (!dsResult.Tables.Contains(liste[i].Table.TableName))
{
dsResult.Tables.Add(liste[i].Table.TableName);
foreach (DataColumn dtCol in liste[i].Table.Columns)
{
if (dsResult.Tables[liste[i].Table.TableName].Columns.Contains("ID"))
dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName+i.ToString());
else
{
dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName);
}
dsResult.Tables[liste[i].Table.TableName].Columns[dtCol.ColumnName].DataType = dtCol.DataType;
}
}
DataRow dRow = dsResult.Tables[liste[i].Table.TableName].NewRow();
dRow.ItemArray = liste[i].ItemArray;
dsResult.Tables[liste[i].Table.TableName].Rows.Add(dRow);
}
IEnumerable<IEnumerable<DataRow>> allTablesRows = dsResult.Tables.Cast<DataTable>()
.Select(table => table.AsEnumerable())
.CartesianProduct();
int k = 0;
foreach (var rows in allTablesRows)
{
DataRow zRow = dsErgebnis.Tables[2].NewRow();
foreach (DataRow dRow in rows)
{
for (int i = 0; i < dRow.ItemArray.Length; i++)
{
zRow[k] = dRow.ItemArray[i];
k++;
}
}
k = 0;
dsErgebnis.Tables[2].Rows.Add(zRow);
}
dsResult.Clear();
}
首先我按ID过滤内容。
然后我将结果放在一个新表格中(我在&#39; Datasatz2&#39;数据集中找到ID为10的所有行&#39; ds&#39;例如我放入一个新表格&#39; 39; Datasatz2&#39;在数据集&#39; dsResult&#39;)。
至少我构建了所有表的笛卡尔积,并将其存储在dtaset dsErgebnis中。
结果是我的期望,但如前所述,我对解决方案不满意。