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(1)); 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(1, "青岛纯生", 10, 30);
this.AddRow(2, "哈尔滨啤酒", 5, 20);
} /// <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(1)); foreach (var obj in query)
{
DataRow dr = DtAll.NewRow();
dr.ItemArray = obj.ToArray();
DtAll.Rows.Add(dr);
}
}
}
}

合并两个dt的更多相关文章

  1. 合并两个结构完全相同的DataTable

    两个结构一模一样的DataTable如何合并? 例子:使用Winform进行演示,表2的数据为固定的,表1的数据可以动态添加,通过合并按钮合并表1和表2的数据到表3 1.规定公共的DataTable结 ...

  2. 如何在Node.js中合并两个复杂对象

    通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢? 例如我有以下两个object: ...

  3. 剑指Offer面试题:16.合并两个排序的链表

    PS:这也是一道出镜率极高的面试题,我相信很多童鞋都会很眼熟,就像于千万人之中遇见不期而遇的人,没有别的话可说,唯有轻轻地问一声:“哦,原来你也在这里? ” 一.题目:合并两个排序的链表 题目:输入两 ...

  4. 【java基础】 合并两个类型相同的list

    将两个类型相同的list合并,可以用 addAll(Collection<? extends E> c) import java.util.ArrayList; import java.u ...

  5. 合并两个有序数组a和b到c

    问题:两个有序数组a和b,合并成一个有序数组c. // 合并两个有序数组a和b到c void Merge_Array(int a[], int n, int b[], int m, int c[]) ...

  6. Python合并两个numpy矩阵

    numpy是Python用来科学计算的一个非常重要的库,numpy主要用来处理一些矩阵对象,可以说numpy让Python有了Matlab的味道. 实际的应用中,矩阵的合并是一个经常发生的操作,如何利 ...

  7. (剑指Offer)面试题17:合并两个排序的链表

    题目: 输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然时按照递增排序的. 链表结点定义如下: struct ListNode{ int val; ListNode* next; }; 思 ...

  8. 剑指Offer15 合并两个已排序链表

    /************************************************************************* > File Name: 15_MergeT ...

  9. java实现合并两个已经排序的列表

    相对于C++来说,Java的最大特点之一就是没有令人困惑的指针,但是我们不可否认,在某些特定的情境下,指针确实算的上一把利刃.虽然Java中没有明确定义出指针,但是由于类的思想,我们可以使用class ...

随机推荐

  1. 利用js添加class

    来来来,开篇点题. 分页应用.当在当前页时,分页的数字有个框之类的. 重要代码如下 <ul class="pagination"> <li><a hr ...

  2. ac1066

    经过分析后的二分 题目是 Josnch星球是一个赌博之风盛行的星球.每个人一出生就有一定数额的钱,之后的所有收入只能由赌博获得(OMG,如果RP不好,输光了所有的 钱...)假设赌博公司的某场赌博有N ...

  3. 20154312 曾林 EXP7 网络欺诈防范

    目录 1.基础问题回答 ----1.1.通常在什么场景下容易受到DNS spoof攻击 ----1.2.在日常生活工作中如何防范以上两攻击方法 2.实践总结与体会 3.实践过程记录 ----3.1.简 ...

  4. python 星号*使用方法

    1.乘号 2.表示倍数 def T(msg,time=1): print((msg+',,')*time) >>>T('hi',3) hi,,hi,,hi 3.单个星号* --1-- ...

  5. python读取剪贴板报错 pywintypes.error: (1418, 'GetClipboardData', '\xcf\xdf\xb3\xcc\xc3\xbb\xd3\xd0\xb4\xf2\xbf\xaa\xb5\x

    在封装读取剪贴板的时候,执行测试代码时遇到个错误: pywintypes.error: (1418, 'GetClipboardData', '\xcf\xdf\xb3\xcc\xc3\xbb\xd3 ...

  6. Shell学习笔记之shell脚本和python脚本实现批量ping IP测试

    0x00 将IP列表放到txt文件内 先建一个存放ip列表的txt文件: [root@yysslopenvpn01 ~]# cat hostip.txt 192.168.130.1 192.168.1 ...

  7. Python3.x:抓取百事糗科段子

    Python3.x:抓取百事糗科段子 实现代码: #Python3.6 获取糗事百科的段子 import urllib.request #导入各类要用到的包 import urllib import ...

  8. lambda表达式Bug——修改捕获变量失败

    解<C++ Primer 5th>的 9-50 练习题时,遇到了 lambda表达式值捕获和引用捕获之区别问题. 欲修改捕获的变量 sum,累加之.但当时忘记值捕获和引用捕获是有区别的.下 ...

  9. Linux进程间通信--使用信号量【转】

    本文转载自:http://blog.csdn.net/ljianhui/article/details/10243617 这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号 ...

  10. Linux下替换默认版本的protobuf

    1. 下载 下载地址,我下载的是protobuf-all-3.5.0.tar.gz,尽量下载all,里面包含protobuf库的所有文件. 2. 编译 ./configure make make in ...