aswin kumar Ответов: 3

Как сравнить 2 таблицы данных и вернуть повторяющиеся значения в C#


У меня есть требование, в котором у меня есть две таблицы данных, обе с разными наборами столбцов, строки являются динамическими. Я хочу сравнить значения в 5-м столбце одной таблицы данных с 4-м столбцом 2-й Таблицы данных и вернуть новую таблицу данных, в которой присутствуют только совпадающие значения.

Таблицы данных-это system.Data.объект DataTable

Я полный новичок, и ваша помощь будет очень полезна для меня.

Таблица данных 1 выглядит следующим образом

xxyy    2   Enjoy 2000 MB                      xxyy 88035
yyxx    2   Enjoy 250 Minutes                  yyxx 88039
yyxx    2   Get 1 GB Data, valid for 3 day.    yyxx 88549
zzyy    2   10 GB Data   valid for 30 days.    zzyy 88535


Таблица данных 2 как показано ниже

2   Enjoy 2000 MB                      xxyy 88035 john
2   Enjoy 250 Minutes                  yyxx 88039 george
2   Get 1 GB Data, valid for 3 day.    yyxx 88612 anil
2   10 GB Data   valid for 30 days.    zzyy 88992 peter


Здесь я пытаюсь сравнить значения в столбце 5 таблицы данных 1 и столбце 4 таблицы данных 2, результат должен быть таким, как показано ниже

xxyy    2   Enjoy 2000 MB        xxyy   88035
yyxx    2   Enjoy 250 Minutes    yyxx   88039

то есть если значения являются общими, верните datatable1 с удалением уникальных значений.

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

Я полный новичок и понятия не имею с чего начать

3 Ответов

Рейтинг:
16

Maciej Los

Если вы хотите получить совпадающие записи, используйте предложение Join (Справочник по c#) | Майкрософт документы[^]

Например:

DataTable dt1 = new DataTable();
dt1.Columns.AddRange(new DataColumn[]
	{
		new DataColumn(),
		new DataColumn(),
		new DataColumn(),
		new DataColumn(),
		new DataColumn()
	});
dt1.Rows.Add(new object[]{"xxyy", 2, "Enjoy 2000 MB", "xxyy", 88035});
dt1.Rows.Add(new object[]{"yyxx", 2, "Enjoy 250 Minutes", "yyxx", 88039});
dt1.Rows.Add(new object[]{"yyxx", 2, "Get 1 GB Data, valid for 3 day.", "yyxx", 88549});
dt1.Rows.Add(new object[]{"zzyy", 2, "10 GB Data   valid for 30 days.", "zzyy", 88535});

DataTable dt2 = new DataTable();
dt2.Columns.AddRange(new DataColumn[]
	{
		new DataColumn(),
		new DataColumn(),
		new DataColumn(),
		new DataColumn(),
		new DataColumn()
	});
dt2.Rows.Add(new object[]{2, "Enjoy 2000 MB", "xxyy", 88035, "john"});
dt2.Rows.Add(new object[]{2, "Enjoy 250 Minutes", "yyxx", 88039, "george"});
dt2.Rows.Add(new object[]{2, "Get 1 GB Data, valid for 3 day.", "yyxx", 88612, "anil"});
dt2.Rows.Add(new object[]{2, "10 GB Data   valid for 30 days.", "zzyy", 88992, "peter"});

var result = from d1 in dt1.AsEnumerable()
	join d2 in dt2.AsEnumerable() on new {A = d1[1], B = d1[4]} equals new {A = d2[0], B = d2[3]}
	select d1;
	
foreach (DataRow dr in result)
{
	Console.WriteLine("{0} {1} {2} {3} {4}", dr[0], dr[1], dr[2], dr[3], dr[4]);
}



Удачи вам!


aswin kumar

Дорогой Мацей,
Спасибо за помощь, но обе эти таблицы данных не имеют никакого заголовка, можем ли мы сделать это на основе индекса?

Maciej Los

Да, ты можешь. Воспользуйся d1[index] вместо d1.Field<string>("ColumnName1")- но я почти уверен , что там есть список столбцов с их именами.

aswin kumar

Спасибо Iosmac,
когда я попробовал с индексом, я получаю ошибку, как показано ниже
"Недопустимый анонимный член-Декларатор типа. Анонимные члены типа должны быть объявлены с назначением члена, простым именем или доступом к члену."

я использовал приведенный ниже код

общественные объект DataTable инструкции(объект DataTable ст1, ст2 объекта DataTable)
{
ВАР результат = у Д1 ст1.Методом asenumerable()
join d2 in dt2.AsEnumerable() on new {d1[6]} равно new {d2[2]}
выберите d1;

вернуться ст1;
}

Maciej Los

Когда вы используете только одно поле, вам не нужен оператор [new] : Скрыть   скопировать код

d1[0] equals d2[2]

[РЕДАКТИРОВАТЬ]
См. обновленный ответ.

aswin kumar

привет изомак,

сценарий был проверен, но когда я пытаюсь вернуть datatable1 после объединения , он дает мне только тот же самый предыдущий Datatable1, а не объединенный.

общественные объект DataTable инструкции(объект DataTable ст1, ст2 объекта DataTable)
{
ВАР результат = у Д1 ст1.Методом asenumerable()
присоединяйтесь к d2 в dt2.AsEnumerable() на d1[1].ToString() равно d2[6].Метод toString()
выберите d1;

вернуться ст1;
}

Maciej Los

Вы не упомянули, что хотите вернуть общие данные для dt1 и dt2. Посмотрите и на свой "выход"... Разве это не похоже на данные dt1?

aswin kumar

да, iosmac, я обнаружил ошибку и использовал приведенный ниже код для вывода данных.

возвращаемый результат.Any()?результат.CopyToDataTable():новый DataTable();

и это сработало, но если есть дубликаты значений, то они также поступают на выход, так или иначе я могу отфильтровать их, ?

извините за назойливые вопросы, я только на стадии обучения . пожалуйста, помогите мне здесь.

Maciej Los

Если вы хотите удалить "дубликаты", вы можете использовать:

var result = yourActuallQuery.Distinct()

Рейтинг:
1

Gerry Schmitz

Используйте подзапрос "IN" :

IN (Transact-SQL) | Microsoft Docs[^]


aswin kumar

Привет Джерри,
Извините, я забыл упомянуть, что смотрю на System.Data.Datatable, а не таблица БД.

Gerry Schmitz

Затем используйте LINQ.

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/creating-a-datatable-from-a-query-linq-to-dataset

Рейтинг:
1

George Swan

//clone structure of dt1 into new table to store the result
DataTable dt3 = dt1.Clone();
//find index numbers in dt1 not present in dt2
var idsExceptDt2 = dt1.AsEnumerable().Select(r => (long)r.ItemArray[4])
    .Except(dt2.AsEnumerable().Select(r => (long)r.ItemArray[3])).ToArray();

foreach (DataRow r in dt1.Rows)
  {
    //does the row index number match any of the non-duplicate index numbers?
    bool isMatched = idsExceptDt2.Any(id => (long)r.ItemArray[4] == id);
    if (!isMatched)
       {
         dt3.Rows.Add(r.ItemArray);
       }
  }