【问题标题】:How to get what exist in the first datatable and not exist in the second data table in a third one?如何获取第一个数据表中存在的内容而第三个数据表中的第二个数据表中不存在的内容?
【发布时间】:2011-08-09 08:10:58
【问题描述】:

问:

我有两个查询,每个都返回一个DataTable。我想返回另一个DaTaTable,因为(第一个 DataTable 中存在什么而不存在(NOT IN)第二个 DataTable)。

我的查询:

编辑:我把它概括为:

1-DT1:

DataTable dt1 = cc1assiscrsevalDAL.GetAll(int.Parse(Session["course_prof"].ToString()), 0);

2-DT2:

DataTable dt2 = cc1assiscrsevalDAL.GetConfirmedEval(int.Parse(Session["course_prof"].ToString()));

注意:batch_no,crsnum,lect_code 是复合主键


最好的方法是什么?(明智的表现)。 我也想用 LINQ 来做这件事。(如果可能的话)。

【问题讨论】:

  • 任何时候使用 NOT EXISTS 都会对性能造成影响,具体取决于表的大小,因为 NOT EXISTS 会进行完整的表扫描。
  • @Tim:你能以任何方式证明这一点吗?这表示 NOT EXISTS 优化的,因为它是一个半连接 dba.stackexchange.com/questions/4009/… 或者这里是为 MySQL、SQL Server、Oracle 探索的:explainextended.com
  • @gbn - 我基于过去合作过的众多 DBA 告诉我的信息。显然这并不完全正确(就像许多其他笼统的陈述一样)。但是,我仍然认为,最好尽可能避免 NOT EXISTS。
  • @just_name: 哪些表是 EXISTS 和 NOT EXISTS?
  • @Tim:你想你想要的:但不要在公共论坛上发布这样的垃圾......

标签: c# asp.net sql linq


【解决方案1】:
var dt = dt1.AsEnumerable().Except(dt2.AsEnumerable(), new CustomDataRowEqualityComparer()).CopyToDataTable();

    public class CustomDataRowEqualityComparer: IEqualityComparer<DataRow>
        {

            public bool Equals(DataRow x, DataRow y)
            {
                return ((int)x["crsnum"]) == ((int)y["crsnum"])
                    && ((int)x["crsnum_e"]) == ((int)y["crsnum_e"])
                        && ((int)x["crstteng"]) == ((int)y["crstteng"]);
            }

            public int GetHashCode(DataRow obj)
            {
                return ((int)obj["crsnum"]) ^ ((int)obj["crsnum_e"]) ^ ((int)obj["crstteng"]) ;
            }
        }

linq 中有一个名为 except 的扩展方法可以解决您的问题,但我们需要为我在上面的代码中所做的创建一个单独的类。

【讨论】:

  • 这将导致两个查询中的所有记录,但 just_name 不需要包含第二个查询中的记录。
【解决方案2】:
select * 
from (*target_query*) t
join
(
  select batch_no,crsnum,lect_code from (*target_query*) q
  except
  select batch_no,crsnum,lect_code from cc1assiscrseval
) temp on temp.batch_no = t.batch_no and temp.lect_code = t.lect_code, temp.crsnum = t.crsnum 

相当肮脏的解决方案,但我认为您可以通过仅获取所需的 batch_no、crsnum 和 lect_code 来简化它,而无需执行第一次查询两次。但是你必须自己弄清楚。

【讨论】:

  • 结构仍然不同。您要包含/排除哪些键?我不知道你的数据库结构:)
【解决方案3】:

Linq 为您提供了一个 except 方法,因此您可以执行类似的操作

var _differences = dt1.AsEnumerable.Except(dt2.AsEnumerable()); // No checked or tested in VS

您也可以先使用以下方法获取相关列:

var x = From a In dt1
    Select (...relevant columns)

var y = From a In dt2
    Select (...relevant columns)

然后做上面的除外。

HTH!

【讨论】:

    猜你喜欢
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多