0

ここに次のようなSQLクエリがあります。

SELECT R.Extra3 AS 'Practice',
    SUM(DATEDIFF(s, R.Pickup, R.Hangup)) AS 'Seconds',
    COUNT(R.Extra3) AS 'Calls'
FROM Outbound.dbo.Results R
JOIN Outbound.dbo.Queue Q
    ON Q.QueueID = R.QueueID
    AND Q.Attempt = R.Attempt
WHERE R.CampaignId = 1
    AND DATEPART(m, R.Pickup) = DATEPART(m, DATEADD(m, -1, getdate()))
    AND DATEPART(y, R.Pickup) = DATEPART(y, DATEADD(m, -1, getdate()))
GROUP BY R.Extra3

私はこれをプログラムで使用する必要があり、LINQルートに行くことにしました。だからここに私が思いついたものがあります:

IQueryable<PracticeSummary> query = db.Results
    .Join(
        db.Queues,
        r => new { Id = r.QueueID.Value, Attempt = r.Attempt.Value },
        q => new { Id = q.QueueID, Attempt = (byte)q.Attempt },
        (r, q) => r
    )
    .Where(
        r => r.CampaignID == 1
            && r.PickUp.Value.Month == lastMonth
            && r.PickUp.Value.Year == lastMonthYear
    )
    .GroupBy(g => g.Extra3)
    .Select(r => new PracticeSummary
    {
        Practice = r.Key,
        Calls = r.Count(),
        Seconds = (r.Sum(item => EntityFunctions.DiffSeconds(item.PickUp, item.HangUp).Value))
    });

SQLクエリは正しい結果を返しますが、LINQクエリは行の10倍以上を返し、その結果、合計とカウントはそれ以上になります。

生成されたTSQLも調べました。次のようになります。

SELECT 
1 AS [C1], 
[GroupBy1].[K1] AS [Extra3], 
[GroupBy1].[A1] AS [C2], 
[GroupBy1].[A2] AS [C3]
FROM ( SELECT 
        [Filter1].[K1] AS [K1], 
        COUNT([Filter1].[A1]) AS [A1], 
        SUM([Filter1].[A2]) AS [A2]
        FROM ( SELECT 
                [Extent1].[Extra3] AS [K1], 
                1 AS [A1], 
                DATEDIFF (second, [Extent1].[PickUp], [Extent1].[HangUp]) AS [A2]
                FROM  [dbo].[Results] AS [Extent1]
                INNER JOIN [dbo].[Queue] AS [Extent2] ON ([Extent1].[QueueID] = [Extent2].[QueueID]) AND (([Extent1].[Attempt] =  CAST( [Extent2].[Attempt] AS tinyint)) OR (([Extent1].[Attempt] IS NULL) AND ( CAST( [Extent2].[Attempt] AS tinyint) IS NULL)))
                WHERE (1 = [Extent1].[CampaignID]) AND ((DATEPART (month, [Extent1].[PickUp])) = @p__linq__0) AND ((DATEPART (year, [Extent1].[PickUp])) = @p__linq__1)
        )  AS [Filter1]
        GROUP BY [K1]
)  AS [GroupBy1]

私が知る限り、それは私が持っていて欲しいものとかなり似ています。

だから私の質問は、なぜ結果が異なるのですか?SQLクエリとLINQクエリの違いは何ですか?私は何が欠けていますか?

時間と労力をよろしくお願いします!

編集:

Queue&Resultのクラスは次のとおりです。

public partial class Queue
{
    public long QueueID { get; set; }
    public long CampaignID { get; set; }
    public int Attempt { get; set; }
    public System.DateTime StartTime { get; set; }
    public System.DateTime EndTime { get; set; }
    public string Extra1 { get; set; }
    public string Extra2 { get; set; }
    public string Extra3 { get; set; }
}

public partial class Result
{
    public long ResultID { get; set; }
    public Nullable<long> QueueID { get; set; }
    public Nullable<long> CampaignID { get; set; }
    public Nullable<byte> Attempt { get; set; }
    public Nullable<System.DateTime> PickUp { get; set; }
    public Nullable<System.DateTime> HangUp { get; set; }
    public string Extra1 { get; set; }
    public string Extra2 { get; set; }
    public string Extra3 { get; set; }
}
4

2 に答える 2

1

結果の数が10倍になっている場合は、問題が結合にあることを示しています。クエリをボトムアップで作成し、結果をテストして、結合に問題があるかどうかを判断することをお勧めします。

最初にこれを試してください:

IQueryable<PracticeSummary> query = db.Results
    .Join(
        db.Queues,
        r => new { Id = r.QueueID.Value, Attempt = r.Attempt.Value },
        q => new { Id = q.QueueID, Attempt = (byte)q.Attempt },
        (r, q) => new { ResultID = r.ResultID, QueueID = q.QueueID
    );

foreach (var result in query)
{
    // See what you have got
}

たぶん、最初の場所で行う方が簡単でしょう:

IQueryable<PracticeSummary> query = db.Results
    .Where(
        r => r.CampaignID == 1
            && r.PickUp.Value.Month == lastMonth
            && r.PickUp.Value.Year == lastMonthYear
    )
    .Join(
        db.Queues,
        r => new { Id = r.QueueID.Value, Attempt = r.Attempt.Value },
        q => new { Id = q.QueueID, Attempt = (byte)q.Attempt },
        (r, q) => new { ResultID = r.ResultID, QueueID = q.QueueID
    );

foreach (var result in query)
{
    // See what you have got
}
于 2013-01-11T16:22:39.257 に答える
0

Results.AttemptとQueue.Attemptの値にnullが含まれている可能性はありますか?

その場合、次のステートメントは、結果のすべての行にnullを掛けます。

OR (([Results].[Attempt] IS NULL) AND ( CAST( [Queue].[Attempt] AS tinyint) IS NULL))
于 2013-01-11T15:24:58.933 に答える