【问题标题】:SQL to LINQ handling Match in Left outer JOIN左外连接中的 SQL 到 LINQ 处理匹配
【发布时间】:2019-03-10 21:40:01
【问题描述】:

我正在尝试将下面的 SQL 转换为 LINQ 查询,但我无法使用左外连接中的匹配来过滤结果。

SELECT @batchID , IQ1.ID, @environment , 'IRD', IQ1.ReportingDate, IQ1.Match
FROM    (
        SELECT  TD.*, RD.Match
        FROM    TransactionDetail TD
                INNER JOIN .dbo.Measure M ON M.InternalID = TD.MetricCode-- and TD.BatchID = 'e07f9855-b286-4406-9189-5cfb2a7914c8'
                LEFT OUTER JOIN (
                    SELECT tmp.ID, tmp.ReportingDate, 1 AS Match
                    FROM tmp
                ) AS RD ON RD.ID = M.Frequency AND RD.ReportingDate = TD.ReportingDate
        WHERE   RD.Match IS NULL AND
                TD.BatchID = @batchID AND
                NOT EXISTS (SELECT TransactionFailureReasonID FROM TransactionDetailFailureReasons R WHERE R.TransactionDetailID = TD.ID and R.TransactionFailureReasonID = 'NRD') AND
                NOT EXISTS (SELECT TransactionFailureReasonID FROM TransactionDetailFailureReasons R WHERE R.TransactionDetailID = TD.ID and R.TransactionFailureReasonID = 'RDP') AND
                NOT EXISTS (SELECT TransactionFailureReasonID FROM TransactionDetailFailureReasons R WHERE R.TransactionDetailID = TD.ID and R.TransactionFailureReasonID = 'RDF')
        ) AS IQ1

到目前为止,我已经取得了以下成就,

// Prepare data for left outer join
        var rd = (from tt in result
                  select new { ID = tt.Id, tt.ReportingDate });

        // inner join
        var td = TransactionDetail.Join(
            MesureTb,
            t => t.MetricCode,
            m => m.InternalId,
            (t, m) => new
            {
                t.Id,
                t.RowAction,
                t.BatchId,
                t.TrustCode,
                t.MetricCode,
                t.ReportingDate,
                t.Value,
                t.UpperBenchmark,
                t.LowerBenchmark,
                m.InternalId,
                Frequency = m.Frequency
            });

        // left outer join
        var failureTransactionDetail = (from p in td
                                        join q in rd on new { ReportingDate = (DateTime)p.ReportingDate, ID = p.Frequency } equals new { q.ReportingDate, q.ID }
                                        into LJ
                                        //select new { p.Id, p.BatchId, p.ReportingDate, RD = q.ReportingDate, q.ID, p.Frequency });
                                        from value in LJ.DefaultIfEmpty()
                                        //where p.BatchId == batchId
                                        select new {p.BatchId,  p.Id, Match = 1, p.ReportingDate } into DJ
                                        // LEFT OUTER JOIN
                                        where DJ.BatchId == batchId
                                        ////&& DJ.Match == 0
                                        && !(TransactionDetailFailureReasons.Any(m => m.TransactionDetailId == DJ.Id && m.TransactionFailureReasonId == "NRD"))
                                        && !(TransactionDetailFailureReasons.Any(m => m.TransactionDetailId == DJ.Id && m.TransactionFailureReasonId == "RDP"))
                                        && !(TransactionDetailFailureReasons.Any(m => m.TransactionDetailId == DJ.Id && m.TransactionFailureReasonId == "RDF"))
                                        select new { DJ.Id, DJ.ReportingDate, DJ.BatchId } );

我的问题是如何在 Linq 的 SQL 中实现与 1 AS Match 类似的结果。

有人可以指导我吗?目前 SQL 查询基于 Match 值为 null 返回 2 个结果,但 LInq 返回 8 个结果,因为它没有过滤左连接匹配。

非常感谢任何帮助。

提前致谢。

【问题讨论】:

  • 在 sql 设置中 1 as Match 只为所有行输出数字 1。你不应该设置 Match = 1 而不是 true 吗?
  • 我确实尝试了 1 但这不会过滤值,我认为我的 Linq 查询存在一些问题。

标签: c# sql .net linq


【解决方案1】:

我只是想在这里帮助你,因为这个问题有点不清楚。但只是将您的 sql 语句与您的 linq 查询进行比较,我可以看到您可能正在尝试过滤 where:RD.Match IS NULL?如果该假设是正确的,那么您的 linq 查询就有问题。

给定以下对象:

public class TransactionDetail
{
    public TransactionDetail(int id, 
        int batchId, 
        int metricCode, 
        DateTime reportingDate)
    {
        Id = id;
        BatchId = batchId;
        MetricCode = metricCode;
        ReportingDate = reportingDate;
    }

    public int Id { get; }
    public int BatchId { get; }
    public int MetricCode { get; }
    public DateTime ReportingDate { get; }
}

public class Measure
{
    public Measure(int internalId, 
        int frequency)
    {
        InternalId = internalId;
        Frequency = frequency;
    }

    public int InternalId { get; }
    public int Frequency { get; }
}

public class Tmp
{
    public Tmp(int id, 
        DateTime reportingDate)
    {
        Id = id;
        ReportingDate = reportingDate;
    }

    public int Id { get; }
    public DateTime ReportingDate { get; }
}

示例代码:

    static void Main(string[] args)
    {
        var transactionDetails = new List<TransactionDetail>
        {
            new TransactionDetail(id: 1, batchId: 1, metricCode: 1, reportingDate: new DateTime(2019, 1, 1)),
            new TransactionDetail(id: 2, batchId: 1, metricCode: 2, reportingDate: new DateTime(2019, 1, 1))
        };

        var matches = new List<Measure>
        {
            new Measure(internalId: 1, frequency: 1),
            new Measure(internalId: 2, frequency: 3)
        };

        var temporaryList = new List<Tmp>
        {
            new Tmp(1, new DateTime(2019, 1, 1)),
        };

        var transDetails = transactionDetails.Join(
            matches,
            t => t.MetricCode,
            m => m.InternalId,
            (t, m) => new
            {
                t.Id,
                t.BatchId,
                t.MetricCode,
                t.ReportingDate,
                m.InternalId,
                m.Frequency
            })
            .ToList();

        var failureTransactionDetail = transDetails
            .GroupJoin(temporaryList,
                trandetail => new { trandetail.ReportingDate, Id = trandetail.Frequency },
                tmp => new { tmp.ReportingDate, tmp.Id },
                (trandetail, tmp) => new { trandetail, tmp })
            .SelectMany(t => t.tmp.DefaultIfEmpty(), (t, value) => new { t, value, Matches = 1 })
            .Where(arg => !arg.t.tmp.Any());

        Console.WriteLine(JsonConvert.SerializeObject(failureTransactionDetail, Formatting.Indented));

        Console.ReadLine();
    }

检查输出,您会发现您不需要Match = 1.Where(arg =&gt; !arg.t.tmp.Any()) 相当于 RD.Match IS NULL 在您的 sql 查询中。

希望这能让您朝着正确的方向前进。

【讨论】:

  • 非常感谢以上,它确实帮助了很多。
  • 没问题@PUBG 很高兴我能帮上忙。干杯
猜你喜欢
  • 1970-01-01
  • 2011-10-14
  • 2017-10-01
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 1970-01-01
  • 2013-09-09
相关资源
最近更新 更多