1

ここで誰かが私を正しい方向に導くことができることを願っています...

public class SubmissionLog
{  
    public int PKId {get;set;}  
    public int SubmissionId {get;set;}  
    public DateTime Created {get;set;}   
    public int StatusId {get;set;}
}

そして、これはデータです:

1, 123, '1/24/2013 01:00:00', 1  
2, 456, '1/24/2013 01:30:00', 1  
3, 123, '1/25/2013 21:00:00', 2  
4, 456, '1/25/2013 21:30:00', 2  
5, 123, '2/25/2013 22:00:00', 1  
6, 123, '2/26/2013 21:00:00', 2  
7, 123, '2/16/2013 21:30:00', 1 

私がしようとしているのは次のとおりです。特定の日の StatusId 1 から StatusId 2 までの平均時間範囲を知りたいです。

したがって、日付が 2013 年 2 月 26 日であるとしましょう。最初に次のようなリストを取得すると、意味があると思います。

var endlingList = (from sl in db.SubmissionLogs  
    where (DateTime.Now.AddDays(days).Date == sl.Created.Date) // days = passed number of days to make it 2/26/2013  
    && (sl.StatusId == 2)  
    select sl).ToList();

var endingLookup = endlingList.ToLookup(a => a.SubmissionId, a => a.Created); // thought of using lookup because Dictionary doesn't allow duplicates

その後、出発点を見つけようと思いました

var startingList = (from sl in db.SubmissionLogs  
where endingList.Select(a => a.SubmissionId).ToArray().Contains(sl.QuoteId)  
&& sl.StatusId == 1
select sl).ToList();

そして、私がしたことは次のとおりです。

var revisedList = endingLookup.Select(a =>
new SubmissionInterval {
    SubmissionId = a.Key,
    EndDateTime = endingLookup[a.Key].FirstOrDefault(), //This is where the problem is. This will only grab the first occurance.
    StartDateTime = startLookup[a.Key].FirstOrDefault() //This is where the problem is. This will only grab the first occurance.
});

そして、平均を取得するために私が行っていることは次のとおりです (繰り返しますが、これには、いくつかの提出 ID 提出ログのステータス 1 およびステータス 2 の最初または最初の出現のみが含まれます)。

return revisedList.Count() > 0 ? revisedList.Select(a=> a.EndDateTime.Subtract(a.StartDateTime).TotalHours).Average() : 0;

だから、まずここで私の問題が何であるかを誰かが理解してくれることを願っています...要約すると、各ステータス1と2の間のタイムスパンを取得したいと思います。これにより、確実に 1 を見つけることができます。私が逆に行って 1 を探した場合、2 は存在しない可能性があります (とにかくそれは望ましくありません)。

最後に、私は物事を平均化できるようにしたい...だから、最初に5時間のスパンで1から2になった提出物があるとしましょう(私が残したコードは、この時点に私を連れて行ってくれます)。 1 に再割り当てされ、その後 6 時間の新しい期間で 2 に戻ったとします。両方を取得して平均を実行できるようにしたいので、(5+6)/2.

ありがとう

4

1 に答える 1

1

私はあなたが何をしようとしているのか理解していると思います。これは役に立ちますか

void Main()
{
    var list = new List<SubmissionLog>
    {
        new SubmissionLog(1, 123, "1/24/2013 01:00:00", 1),
        new SubmissionLog(2, 456, "1/24/2013 01:30:00", 1),
        new SubmissionLog(3, 123, "1/25/2013 21:00:00", 2),
        new SubmissionLog(4, 456, "1/25/2013 21:30:00", 2),
        new SubmissionLog(5, 123, "2/25/2013 22:00:00", 1),
        new SubmissionLog(6, 123, "2/26/2013 21:00:00", 2),
        new SubmissionLog(7, 123, "2/16/2013 21:30:00", 1),
    };

    // split out status 1 and 2
    var s1s = list.Where (l => l.StatusId == 1).OrderBy (l => l.Created);
    var s2s = list.Where (l => l.StatusId == 2).OrderBy (l => l.Created);

    // use a sub-query to get the first s2 after each s1
    var q = s1s.Select (s1 => new 
        {
            s1, 
            s2 = s2s.FirstOrDefault (s2 => 
                s1.SubmissionId == s2.SubmissionId &&
                s2.Created >= s1.Created    
            )
        }
    ).Where (s => s.s1.PKId < s.s2.PKId && s.s2 != null);

        // extract the info we need 
        // note that TotalSecond is ok in Linq to Object but you'll 
        // probably need to use SqlFunctions or equivalent if this is to 
        // run against a DB.
    var q1 = q.Select (x => new 
        {
            Start=x.s1.Created,
            End=x.s2.Created,
            SubmissionId=x.s1.SubmissionId, 
            Seconds=(x.s2.Created - x.s1.Created).TotalSeconds
        }
    );

        // group by submissionId and average the time
    var q2 = q1.GroupBy (x => x.SubmissionId).Select (x => new {
        x.Key, 
        Count=x.Count (),
        Start=x.Min (y => y.Start),
        End=x.Max (y => y.End),
        Average=x.Average (y => y.Seconds)});
}

public class SubmissionLog
{  
    public SubmissionLog(int id, int submissionId, string date, int statusId)
    {
        PKId = id;
        SubmissionId = submissionId;
        Created = DateTime.Parse(date, CultureInfo.CreateSpecificCulture("en-US"));
        StatusId = statusId;
    }
    public int PKId {get;set;}  
    public int SubmissionId {get;set;}  
    public DateTime Created {get;set;}   
    public int StatusId {get;set;}
}
于 2013-02-08T10:39:38.087 に答える