C#代码中实现两个表(DataTable)的关联查询(JOIN)
之前通常都是使用SQL直接从数据库中取出表1和表2关联查询后的数据,只需要用一个JOIN就可以了,非常方便。近日遇到一种情况,两个表中的数据已经取到代码中,需要在代码中将这两个表关联起来,并得到它们横向拼在一起之后的完整数据。
如:表1--商品信息表(dtHead),存放商品的ID和名称,表结构和数据如下:
表2--商品数量及金额表(dtTail),存放商品的数量、金额,表结构和数据如下:


现在要得到表1和表2横向拼接起来的表(DtAll),结果如下:
在C#代码中,要将这两个表拼接起来,有很多笨办法,例如循环获取数据一条条拼起来,但在数据量大的情况下会影响性能,在字段多的时候也需要写一大堆给每个字段依次赋值的代码。
使用LINQ可以帮助解决这一问题。下面提供了两种方案:
方案一:当能够确定DtAll表的字段,并且字段不是很多的情况下,可以显式写出:
var query1 =
from rHead in dtHead.AsEnumerable()
from rTail in dtTail.AsEnumerable()
where rHead.Field<Int32>("GoodID") == rTail.Field<Int32>("GoodID")
select new
{
GoodID = rHead.Field<Int32>("GoodID"),
GoodName = rHead.Field<String>("GoodName"),
Num = rTail.Field<Int32>("Num"),
Money = rTail.Field<Int32>("Money")
}; DataTable dtNew = DtAll.Copy();
foreach (var obj in query1)
{
dtNew.Rows.Add(obj.GoodID, obj.GoodName, obj.Num, obj.Money);
}
其中DtAll的表结构已经事先创建好了,在下面会给出所有代码。
方案二:LINQ提供了与SQL中类似的JOIN方法。并且当字段很多的情况下,每一个字段都在select new中写出来比较麻烦,可以使用如下的方式:
var query =
from rHead in dtHead.AsEnumerable()
join rTail in dtTail.AsEnumerable()
on rHead.Field<Int32>("GoodID") equals rTail.Field<Int32>("GoodID")
select rHead.ItemArray.Concat(rTail.ItemArray.Skip()); foreach (var obj in query)
{
DataRow dr = DtAll.NewRow();
dr.ItemArray = obj.ToArray();
DtAll.Rows.Add(dr);
}
使用Concat将表1和表2的字段拼接起来,作为总表DtAll的字段,但由于表1、表2中都存在字段GoodID,不能在表中出现重复的字段,因此使用Skip(1)跳过表2中的第一个字段GoodID。
下面给出这个小例子完整的代码(不包括窗体,窗体上很简单,只有一个按钮)
首先写入测试数据:把表1、表2创建起来并插入如上图所示的数据(实际情况是表1、表2通过其他渠道直接获取到代码中的)
然后在单击“连接”按钮时,得到表1、表2横向连接后的表:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data; namespace WpfApplication1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
DataTable dtHead = new DataTable();
DataTable dtTail = new DataTable();
DataTable DtAll = new DataTable(); public MainWindow()
{
InitializeComponent(); this.AddData();
} /// <summary>
/// 创建表结构,添加数据源
/// </summary>
private void AddData()
{
dtHead.Columns.Add("GoodID", typeof(Int32));
dtHead.Columns.Add("GoodName", typeof(String)); dtTail.Columns.Add("GoodID", typeof(Int32));
dtTail.Columns.Add("Num", typeof(Int32));
dtTail.Columns.Add("Money", typeof(Int32)); DtAll.Columns.Add("GoodID", typeof(Int32));
DtAll.Columns.Add("GoodName", typeof(String));
DtAll.Columns.Add("Num", typeof(Int32));
DtAll.Columns.Add("Money", typeof(Int32)); this.AddRow(, "青岛纯生", , );
this.AddRow(, "哈尔滨啤酒", , );
} /// <summary>
/// 添加数据
/// </summary>
/// <param name="goodID"></param>
/// <param name="goodName"></param>
/// <param name="num1"></param>
/// <param name="num2"></param>
private void AddRow(Int32 goodID, String goodName, Int32 num1,Int32 num2)
{
DataRow drH = dtHead.NewRow();
drH["GoodID"] = goodID;
drH["GoodName"] = goodName;
dtHead.Rows.Add(drH); DataRow drT = dtTail.NewRow();
drT["GoodID"] = goodID;
drT["Num"] = num1;
drT["Money"] = num2;
dtTail.Rows.Add(drT);
} /// <summary>
/// “连接”按钮单击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Join_Click(object sender, RoutedEventArgs e)
{
//方案一
var query1 =
from rHead in dtHead.AsEnumerable()
from rTail in dtTail.AsEnumerable()
where rHead.Field<Int32>("GoodID") == rTail.Field<Int32>("GoodID")
select new
{
GoodID = rHead.Field<Int32>("GoodID"),
GoodName = rHead.Field<String>("GoodName"),
Num = rTail.Field<Int32>("Num"),
Money = rTail.Field<Int32>("Money")
}; DataTable dtNew = DtAll.Copy();
foreach (var obj in query1)
{
dtNew.Rows.Add(obj.GoodID, obj.GoodName, obj.Num, obj.Money);
} //方案二
var query =
from rHead in dtHead.AsEnumerable()
join rTail in dtTail.AsEnumerable()
on rHead.Field<Int32>("GoodID") equals rTail.Field<Int32>("GoodID")
select rHead.ItemArray.Concat(rTail.ItemArray.Skip()); foreach (var obj in query)
{
DataRow dr = DtAll.NewRow();
dr.ItemArray = obj.ToArray();
DtAll.Rows.Add(dr);
}
}
}
}



C#代码中实现两个表(DataTable)的关联查询(JOIN)的更多相关文章
- 关于表 datatable的条件查询
关于表 datatable的条件查询 从数据库中获得一个datatable dt .里面有很多的死的数据.然后,我就是要在这个表中来按条件查询,例如 dt中有个列叫"palte", ...
- SQL中order by;group up;like;关联查询join on的用法
排序order by的用法: 1.order by 字段名1 asc/desc, 字段名2 asc/desc,... 先按照字段名1的升序/降续给表进行排列 然后 按照字段名2的升序/降续给表进行排列 ...
- MyBitis(iBitis)系列随笔之五:多表(一对多关联查询)
MyBitis(iBitis)系列随笔之一:MyBitis入门实例 MyBitis(iBitis)系列随笔之二:类型别名(typeAliases)与表-对象映射(ORM) MyBitis(iBitis ...
- SQL Server中取两个表的交集,并集和差集
在项目中遇到要取两个表差集的情况 假设有两个表tblNZPostCodes, NZPostcode 两个表中存储的都是新西兰的post code信息,字段一致,只是数据上有所差异. 1. Union ...
- vue同一页面中拥有两个表单时,验证问题
问题:如果vue的同一个页面拥有两个表单.验证第一个表单时没有通过就切换到第二个,那么第二个表单会出现验证错误的信息 我们可以通过为两个表单添加ref属性 之后在通过调用resetFields()方法 ...
- 使用SQL语句将数据库中的两个表合并成一张表
select * into 新表名 from (select * from T1 union all select * from T2) 这个语句可以实现将合并的数据追加到一个新表中. 不合并重复数 ...
- SQL中合并两个表的JOIN语句
SQL里有四种JOIN语句用于根据某条件合并两个表: (INNER) JOIN: 交集 LEFT (OUTER) JOIN: 左表数据全包括,右表对应的如果没有就是NULL RIGHT (OUTER) ...
- @ManyToMany 两个表多对多关联
两个表属于多对多关系 如 Teacher <=> Student 表teacher 主键 id 表student 主键id 中间关联表 teacher_student 两个字段 t_id ...
- ofbiz多表外键关联查询
实现一:Screem.xml 中的 section 里,加 <action>, 加 get-related 实现二:在代码中使用 DynamicViewEntity对象,加入addMemb ...
随机推荐
- iis7.0与asp.net的运行原理
IIS7.0 IIS7.0主要引入了WAS(Windows Process Activation,不同于6.0中的Web Admin Service),分担了原来w3svc的部分功能,同时为IIS7. ...
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...
- JDBC_part1_Oracle数据库连接JDBC以及查询语句
本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! JDBC part1 JDBC概述 jdbc是一种用于 ...
- Is-A,Has-A,Use-A(转载)
原文地址:http://blog.csdn.net/loveyou128144/article/details/4749576 而Is-A,Has-A,Use-A则是用来描述类与类之间关系的.简单的说 ...
- Quartz —— Spring 环境下的使用
一.在 Spring 环境下 Quartz 的使用超级简单. 二.具体使用 1.添加对应的 spring-quartz 的配置文件. 2.新建要执行定时任务的目标类和目标方法,不需要继承 Job 接口 ...
- 为什么applicationContext.xml和spring-servlet.xml中都有注解过滤<context:component-scan base-package="myproject"> 和<context:component-scan base-package="myproject.controller" />
在刚学习SpringMVC框架整合时,你也许会产生疑问为什么Spring.xml和SpringMVC.xml中都有注解过滤. <context:component-scan base-packa ...
- 来玩Play框架07 静态文件
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Play框架的主要功能是提供动态响应的内容.但一个网络项目中必然有大量的静态内容, ...
- gRPC源码分析2-Server的建立
gRPC中,Server.Client共享的Class不是很多,所以我们可以单独的分别讲解Server和Client的源码. 通过第一篇,我们知道对于gRPC来说,建立Server是非常简单的,还记得 ...
- HashSet,TreeSet和LinkedHashSet的区别
Set接口Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个对象用eq ...
- ArcGIS Engine开发之量测功能
1.距离测量 距离测量时,片段长度通过两点之间距离计算得到,全部长度通过片段长度的和计算得到.主要用到INewLineFeedback和IScreenDisplay两个接口. 1)INewLineFe ...