pcprogrammer9 Ответов: 2

Слияние двух таблиц данных на основе одного первичного столбца В C#


У меня есть две таблицы данных(у меня нет никакой таблицы базы данных, просто простая таблица данных), как показано на скриншоте (datatable1 и datatable2).

DataTable datatable1= new DataTable();
 new_Table.Columns.Add("Name");
 new_Table.Columns.Add("Number_A");
 new_Table.Columns.Add("Comment");
 new_Table.Columns.Add("ID");

DataTable datatable2= new DataTable();
 new_Table.Columns.Add("Name");
 new_Table.Columns.Add("Number_B");
 new_Table.Columns.Add("Age");
 new_Table.Columns.Add("City");


скриншот

после связывания их я хочу сравнить две таблицы данных и объединить строки с аналогичным значением столбца "имя", а также добавить другие строки, как вы видите на скриншоте, и создать новую таблицу данных с именем result datatable...

Не могли бы вы объяснить мне, как этого добиться?

Спасибо

Что я уже пробовал:

у меня нет никакой идеи для слияния этих таблиц

2 Ответов

Рейтинг:
2

OriginalGriff

В принципе, ваши таблицы плохо спроектированы, и между ними нет "гарантированной" связи - единственный столбец, который существует в обеих таблицах, - это "имя", и это не уникально, даже в небольших группах. Вспомните свои школьные годы - сколько детей только в вашем классе имели общее имя? По мере увеличения размера выборки вероятность появления дубликатов также возрастает, и один дубликат ужасно испортит ваши результаты. Подумайте об этом: даже с Днями рождения смена дубликата достигает 99,9% вероятности всего с 70 людьми и 50% вероятности с 23 людьми - так что имена-это реальный риск!

Вам нужно перепроектировать свои структуры данных, прежде чем вы начнете "объединять таблицы": имя должно быть в третьей таблице с уникальным столбцом идентификатора, чтобы разрешить дубликаты, а две другие таблицы должны ссылаться на значение идентификатора как на внешний ключ.
Тогда это тривиально: простое соединение сделает то, что вы хотите.


Рейтинг:
0

Maciej Los

Прежде всего, я согласен с OriginalGriff.

Вы можете создать "объединенную таблицу" с помощью Linq. Видеть:

//first
DataTable dt1= new DataTable();
dt1.Columns.Add("Name", typeof(string));
dt1.Columns.Add("Number_A", typeof(int));
dt1.Columns.Add("Comment", typeof(string));
dt1.Columns.Add("ID", typeof(int));
dt1.Rows.Add(new object[]{"John", 25800, "text", 12});
dt1.Rows.Add(new object[]{"Jack", 35801, "text", 10});
dt1.Rows.Add(new object[]{"Tom", 92412, "text", 3});
dt1.Rows.Add(new object[]{"Max", 92415, "text", 6});
dt1.Rows.Add(new object[]{"Bob", 68752, "text", 19});
//second
DataTable dt2= new DataTable();
dt2.Columns.Add("Name", typeof(string));
dt2.Columns.Add("Number_B", typeof(int));
dt2.Columns.Add("Age", typeof(int));
dt2.Columns.Add("City", typeof(string));
dt2.Rows.Add(new object[]{"Rose", 92610, 24, "London"});
dt2.Rows.Add(new object[]{"Jack", 25813, 21, "Paris"});
dt2.Rows.Add(new object[]{"Tom", 65291, 26, "Newyork"});
dt2.Rows.Add(new object[]{"John", 76241, 31, "Rome"});
dt2.Rows.Add(new object[]{"Mat", 38516, 27, "Paris"});
//result table
DataTable dt3 = new DataTable();
dt3.Columns.Add("Name", typeof(string));
dt3.Columns.Add("Number_A", typeof(int));
dt3.Columns.Add("Comment", typeof(string));
dt3.Columns.Add("ID", typeof(int));
dt3.Columns.Add("Number_B", typeof(int));
dt3.Columns.Add("Age", typeof(int));
dt3.Columns.Add("City", typeof(string));

//get common data and insert into result datatable
dt3 = (from d1 in dt1.AsEnumerable()
	join d2 in dt2.AsEnumerable() on d1.Field<string>("Name") equals d2.Field<string>("Name")
	select dt3.LoadDataRow(new object[]
	{
		d1.Field<string>("Name"),
		d1.Field<int>("Number_A"),
		d1.Field<string>("Comment"),
		d1.Field<int>("ID"),
		d2.Field<int>("Number_B"),
		d2.Field<int>("Age"),
		d2.Field<string>("City")
	}, false))
	.CopyToDataTable();

//get dt1 specific data (not in common)
var dt1spec = (from d1 in dt1.AsEnumerable()
	select new
	{
		Name = d1.Field<string>("Name"),
		Number_A = d1.Field<int>("Number_A"),
		Comment = d1.Field<string>("Comment"),
		ID = d1.Field<int>("ID")
	})
	.ToList()
	.Except(from d3 in dt3.AsEnumerable()
		select new
		{
			Name = d3.Field<string>("Name"),
			Number_A = d3.Field<int>("Number_A"),
			Comment = d3.Field<string>("Comment"),
			ID = d3.Field<int>("ID")
		})
	.ToList();

//get dt2 specific data (not in common)
var dt2spec = (from d2 in dt2.AsEnumerable()
	select new
	{
		Name = d2.Field<string>("Name"),
		Number_B = d2.Field<int>("Number_B"),
		Age = d2.Field<int>("Age"),
		City = d2.Field<string>("City")
	})
	.ToList()
	.Except(from d3 in dt3.AsEnumerable()
		select new
		{
			Name = d3.Field<string>("Name"),
			Number_B = d3.Field<int>("Number_B"),
			Age = d3.Field<int>("Age"),
			City = d3.Field<string>("City")
		})
	.ToList();
	
//add dt1spec data
foreach(var data in dt1spec)
{
	dt3.Rows.Add(new object[]{data.Name, data.Number_A, data.Comment, data.ID, null, null, null});
}
//add dt2spec data
foreach(var data in dt2spec)
{
	dt3.Rows.Add(new object[]{data.Name, null, null, null, data.Number_B, data.Age, data.City});
}