【问题标题】:Linq query returning duplicatesLinq 查询返回重复项
【发布时间】:2014-10-11 00:32:36
【问题描述】:

所以我有两个数据表,都取自同一个 ODBC 数据源。一个有销售行 (Estado='VENTAS'),另一个有 Estado='EXIST' 行(数据库为每次销售创建行对,一个表示销售信息,另一个表示有关商店存款的库存变动信息,因此在为了知道哪家商店进行了销售,我必须将每个 VENTAS 行与相应的 EXIST 行匹配 [通过“Documento” ID 字段],并从 Exist 行中获取“Deposito”值。

我构建了这个查询来做到这一点(我使用的 ODBC 驱动程序不允许连接,所以在 Linq 中这样做是下一个最好的事情)

            DataTable dtResult = new DataTable();

            dtResult.Columns.Add("Documento", typeof(Int64)); 
            dtResult.Columns.Add("Fecha", typeof(DateTime));
            dtResult.Columns.Add("Articulo", typeof(string));
            dtResult.Columns.Add("Deposito", typeof(string));
            dtResult.Columns.Add("ImpDMn", typeof(decimal));
            dtResult.Columns.Add("Cantidad", typeof(decimal));
            dtResult.Columns.Add("Partida", typeof(string));

            var result = from dataRows1 in VentasDT.AsEnumerable() //VentasDT is the DataTable with the VENTAS data
                         join dataRows2 in ExistDT.AsEnumerable() // ExistDT is the DataTable with the EXIST data
                         on dataRows1.Field<Int64>("Documento") equals dataRows2.Field<Int64>("Documento")
                         select dtResult.LoadDataRow(new object[]
         {
            dataRows1.Field<Int64>("Documento"),
            dataRows1.Field<DateTime>("Fecha"),
            dataRows1.Field<string>("Articulo"),
            dataRows2.Field<string>("Deposito"),
            dataRows1.Field<decimal>("ImpDMn"),
            dataRows1.Field<decimal>("Cantidad"),
            dataRows1.Field<string>("Partida"),
          }, false);
            result.CopyToDataTable();

它可以工作,但由于某种原因它重复了 一些 行。 我检查了重复的行,它们彼此相同。他们的文档编号是相等的(每个 Documento 编号只有一个 VENTAS 和一个 EXIST 行,包括这些重复项)所以我不知道他们为什么会被重复。我检查了我要加入的源数据表,同样,每个重复项只有一个对应的行。 EXIST 表比 VENTAS 表大(它还记录非销售商店之间的转移),但连接表比任何一个都大(但没有两者合并的那么大)

VENTAS: 85123
EXIST: 116857
JOIN: 141287

我的查询有问题吗?我应该包含一些 GROUP BY 子句或 .Distinct 还是这种结构(据我所见应该模仿左连接)就足够了?

【问题讨论】:

  • EXIST 表中表示转账的记录能否使其Documento 字段等于VENTAS 中的Documento 字段?
  • 没有。转移有自己独特的 Documento 值,在 Ventas 表中找不到对数,据我所知,连接表中的每个重复项都有一个 Documento 值,该值显示在原始 Ventas 表中(因此不是转移)..

标签: c# linq


【解决方案1】:

由于您执行此连接的唯一原因是从ExistDT 获取"Deposito" 字段的值,因此您可以用字典查找替换连接。以下是你可以做到的:

var depositoPorDocumento = ExistDT.AsEnumerable().ToDictionary(
    dr => dr.Field<Int64>("Documento"),
    dr => dr.Field<string>("Deposito")
);
foreach (var vr in VentasDT.AsEnumerable()) {
    Int64 id = Field<Int64>("Documento");
    string deposito;
    if (!depositoPorDocumento.TryGetValue(id, out deposito)) {
        continue;
    }
    dtResult.LoadDataRow(new object[]
     {
        id,
        vr.Field<DateTime>("Fecha"),
        vr.Field<string>("Articulo"),
        deposito,
        vr.Field<decimal>("ImpDMn"),
        vr.Field<decimal>("Cantidad"),
        vr.Field<string>("Partida"),
      }, false);
}
result.CopyToDataTable();

【讨论】:

  • 您的解决方案给了我很多语法错误: ExistTD.ToDictionary() 上的 (...) 没有定义和扩展方法; foreach 语句无法对 foreach 上的 Datatable (...) 进行操作(VentasDT 中的 var vr;以及 !depositoPorDocumento.TryGetValue(id, out deposito) 上的无效参数 ...?
  • @ConnorU 我不确定VentasDTExistTD 是什么,所以我跳过了.AsEnumerable() 电话。我把它们加回来了,看看这是否编译。
  • 您的解决方案可以编译,但它崩溃了——这向我展示了我在哪里犯了错误:如果售出不止一件商品,每个 Documento 可能包含多行。我先按 Articulo ID 排序我的表格,然后按 Document,所以它们似乎从来没有超过一个,当我进行连接时,程序用它找到的第一个 Articulo 信息替换每一行,所以它似乎是重复的,但它是替换...感谢您的回答,我的问题是错误的,我需要立即编辑它
  • @ConnorU 在ToDictionary 中崩溃了吗?
  • 是的,同一个 Documento 有多行——主键是 Documento 和 Articulo id 值的组合,我之前没有意识到