1 private DataTable dtJoiner(DataTable targetDt, DataTable otherDt)2{3 var rows = from targetDtRow in targetDt.AsEnumerable()4 join otherDtRow in otherDt.AsEnumerable()5 on new { a= targetDtRow.Field<string>("A"), b= targetDtRow.Field<string>("B")} equals new { a= otherDtRow.Field<Int32>("A").ToString(), b= otherDtRow.Field<Int32>("B").ToString()}6 select targetDtRow;78return rows.CopyToDataTable();9}
#追記
テーブル1 テーブル2
A列 B列 C列 A列 B列 D列
1 2 a 1 2 d
1 2 b
1 2 c
のDataTableがあった場合、理想としては結合後のテーブルは
テーブル 3
A列 B列 C列 D列
1 2 a d
1 2 b d
1 2 c d
なのですが実際は
テーブル 3
A列 B列 C列 D列
1 2 a d
1 2 a d
1 2 a d
になってしまいます。
重複させないようにしたいのですが不可能でしょうか?
1 private DataTable dtJoiner(DataTable targetDt, DataTable otherDt)2{3 var response = new DataTable();45 new List<string>{"A","B","C","D"}6.ForEach(c => response.Columns.Add(c,typeof(string)));78 var rows = targetDt.AsEnumerable()9.Join(otherDt.AsEnumerable(),10 t => new { a = t.Field<string>("A"), b = t.Field<string>("B")},11 o => new { a = o.Field<string>("A"), b = o.Field<string>("B")},12(t, o)=>13{14 var row = response.NewRow();15 row.ItemArray = new[]{ t.Field<string>("A"), t.Field<string>("B"), t.Field<string>("C"), o.Field<string>("D")};16return row;17});1819foreach(var row in rows)20{21 response.Rows.Add(row);22}2324return response;25}
PS. DataTable は過去の遺物で、重たく扱いづらい代物です。
また最近の主流であるLINQとは相性が悪いです。
1var rows = targetDt.AsEnumerable()2.Join(otherDt.AsEnumerable(),3 t => new { a = t.Field<string>("A"), b = t.Field<string>("B")},4 o => new { a = o.Field<string>("A"), b = o.Field<string>("B")},5(t, o)=> new
6{7 a = t.Field<string>("A"),8 b = t.Field<string>("B"),9 c = t.Field<string>("C"),10 d = o.Field<string>("D")11})12.Distinct()13.Select(j =>14{15 var row = response.NewRow();16 row.ItemArray = new[]{ j.a, j.b, j.c, j.d };17return row;18});
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleAppDataTableJoinByLinq
{
class Program
{
static void Main(string[] args)
{
// 2 つの DataTable を作成。
DataTable orders = new DataTable();
DataTable customers = new DataTable();
string selectOrders = "SELECT OrderID, CustomerID, ShipCity FROM Orders";
string selectCustomers = "SELECT CustomerID, CompanyName, City FROM Customers";
string connStr = @"Data Source=(local)\sqlexpress;Initial Catalog=NORTHWIND;Integrated Security=True";
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = selectOrders;
adapter.SelectCommand = cmd;
adapter.Fill(orders);
adapter.SelectCommand.CommandText = selectCustomers;
adapter.Fill(customers);
}
var result = from o in orders.AsEnumerable()
join c in customers.AsEnumerable()
on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID")
where o.Field<string>("ShipCity") == c.Field<string>("City")
select new
{
OrderID = o.Field<int>("OrderID"),
CompanyName = c.Field<string>("CompanyName"),
ShipCity = o.Field<string>("ShipCity")
};
foreach (var item in result)
{
Console.WriteLine("OrderID: {0}, CompanyName: {1}, ShipCity: {2}",
item.OrderID, item.CompanyName, item.ShipCity);
}
// 結果は:
// OrderID: 10248, CompanyName: Vins et alcools Chevalier, ShipCity: Reims
// OrderID: 10250, CompanyName: Hanari Carnes, ShipCity: Rio de Janeiro
// OrderID: 10251, CompanyName: Victuailles en stock, ShipCity: Lyon
// ・・・中略・・・
// OrderID: 11077, CompanyName: Rattlesnake Canyon Grocery, ShipCity: Albuquerque
// 結果を DataTable に格納
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("OrderID", typeof(int)));
table.Columns.Add(new DataColumn("CompanyName", typeof(string)));
table.Columns.Add(new DataColumn("ShipCity", typeof(string)));
foreach (var item in result)
{
DataRow row = table.NewRow();
row["OrderID"] = item.OrderID;
row["CompanyName"] = item.CompanyName;
row["ShipCity"] = item.ShipCity;
table.Rows.Add(row);
}
}
}
}
【追記】
コメント欄の追加質問の件です。
条件に一致したデータが複数存在した場合は既に配列に存在した場合はスキップしたい
IEnumerable<T> で T が匿名型の場合(上のコードで言うと result がそれ)は、単純に result に Distinct() メソッドを適用すれば期待通り重複のない結果が得られます。具体的には例えば、以下のようにしてください。
var result = from o in orders.AsEnumerable()
join c in customers.AsEnumerable()
on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID")
where o.Field<string>("ShipCity") == c.Field<string>("City")
select new
{
OrderID = o.Field<int>("OrderID"),
CompanyName = c.Field<string>("CompanyName"),
ShipCity = o.Field<string>("ShipCity")
};
result = result.Distinct(); // この行を追加