当前位置:  开发笔记 > 编程语言 > 正文

Linq查询给出不适当的输出

如何解决《Linq查询给出不适当的输出》经验,为你挑选了2个好方法。

我有一个名为两个交易表ParentTransactionChildTransaction其中TransactionIdParentTransaction将作为外来ChildTransactionTransactionId.

现在我想获得payamount未完成的ParentTransaction的所有TransactionId .

从下面的输出我想要事务Id 3的记录,因为只有1000支付了transactionid3而不是5000.

我有一个这样的表:

Transactionid(p.k)    PayAmount
  1                   1000
  2                   3000
  3                   5000
  4                   6000

ChildTransaction

Id        TransactionId(F.k)   DepositAmount
1           1                  600
2           1                  400
3           2                  1000
4           2                  1000
5           2                  1000
6           3                  2000

这是我的查询:

var data = (from tmp in context.ParentTransaction
            join tmp1 in context.ChildTransaction on tmp.Transactionid equals
            tmp1.Transactionid where tmp.PayAmount !=tmp1.DepositAmount
                    select tmp);

但在这里我得到了交易ID 1和2,尽管他们的交易已经完成了两个部分,即600和400的交易ID 1.



1> Ivan Stoev..:

查询语言的一般概念是表达所需的结果,而不是如何获得它.

将它应用于您的场景会导致这样的简单查询

var query = context.ParentTransaction
   .Where(t => t.PayAmount != context.ChildTransaction
      .Where(ct => ct.TransactionId == t.TransactionId)
      .Sum(ct => ct.DepositAmount));

如果您使用EF和正确的模型导航属性,它甚至会很简单

var query = context.ParentTransaction
    .Where(t => t.PayAmount != t.ChildTransactions.Sum(ct => ct.DepositAmount));

可以说,与@Vadim Martynov的回答相比,上述内容效率低下.好吧,可能是的,可能不是.Vadim试图强制执行一个特定的执行计划,我可以理解 - 当实际遇到查询性能问题时,我们必须做这些事情.但这并不自然,只有在我们遇到性能问题时才应该是最后的手段.在大多数情况下,查询提供程序和SQL查询优化器将为我们做(并且正在做)这项工作,因此我们不需要考虑是否需要使用joinvs subquery等.



2> Vadim Martyn..:

我不确定这!=是否是最好的价值.这是一个>检查和分组的解决方案:

var expectedValue =
            context.ChildTransaction
                .GroupBy(t => t.TransactionId, (key, group) => new { TransactionId = key, Deposit = group.Sum(e => e.Deposit) })
                .Join(context.ParentTransaction, grouped => grouped.TransactionId, transaction => transaction.TransactionId, (group, transaction) => new { Transaction = transaction, group.Deposit })
                .Where(result => result.Transaction.PayAmount > result.Deposit)
                .Select(result => result.Transaction);

可以像下一个要求那样以声明方式读取此查询:

    通过TransactionId和为每个组的子事务的组集合检索具有字段TransactionId =分组键(== TransactionId)和存款的匿名类型对象,存储是具有相同TransactionId的行的存款的总和.

    加入组从第1部分到表PaerntTransactionTransactionId字段.对于每一个连接一对检索匿名类型与字段事务从对象==交易ParentTransactions表和存款其是从第1部分设置其与同一矿床总和存款TransactionIdChildTransactions表.

    仅从结果集中过滤掉PayAmount比存款总和更大的对象.

    仅返回ParentTransaction每个已过滤行的对象.

这是SQL优化的方案,因为连接,过滤和分组可以防止嵌套查询,这些查询可以在其他情况下添加到实际执行计划中,从而降低性能.

UPDATE

要解决没有存款的交易问题,您可以使用LEFT JOIN:

var expectedValue = from parent in context.ParentTransaction
            join child in context.ChildTransaction on parent.TransactionId equals child.TransactionId into gj
            from subset in gj.DefaultIfEmpty()
            let joined = new { Transaction = parent, Deposit = subset != null ? subset.Deposit : 0 }
            group joined by joined.Transaction
            into grouped
            let g = new { Transaction = grouped.Key, Deposit = grouped.Sum(e => e.Deposit) }
            where g.Transaction.PayAmount > g.Deposit
            select g.Transaction;

与LINQ方法链相同的查询:

var expectedValue =
            context.ParentTransaction
                .GroupJoin(context.ChildTransaction, parent => parent.TransactionId, child => child.TransactionId, (parent, gj) => new { parent, gj })
                .SelectMany(@t => @t.gj.DefaultIfEmpty(), (@t, subset) => new { @t, subset })
                .Select(@t => new { @t, joined = new { Transaction = @t.@t.parent, Deposit = @t.subset != null ? @t.subset.Deposit : 0 } })
                .GroupBy(@t => @t.joined.Transaction, @t => @t.joined)
                .Select(grouped => new { grouped, g = new { Transaction = grouped.Key, Deposit = grouped.Sum(e => e.Deposit) } })
                .Where(@t => @t.g.Transaction.PayAmount > @t.g.Deposit)
                .Select(@t => @t.g.Transaction);

现在,您检索所有父事务并将其与子事务连接,但如果没有子事务,则以Deposit == 0类似方式使用和分组已连接的实体ParentTransaction.

推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有