24

현재 선택된 날짜로 결과를 그룹화하는 쿼리를 실행하고 싶습니다.

이 예제에서는 다음과 같은 간단한 모델을 상상해보십시오.

public class User
{
      public DateTime LastLogIn {get; set;}
      public string Name {get; set;}
}

내가 찾고있는 솔루션은 Date로 로그인 한 사용자 수를 얻는 것입니다. 데이터베이스에서 DateTime은 날짜 및 시간 구성 요소와 함께 저장되지만이 쿼리에 대해서는 날짜 만 신경 씁니다.

내가 현재 가지고있는 것은 이것이다.

    context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)EntityFunctions.TruncateTime(x.Key)
            }).ToList();

위의 경우 그러나 빈 목록을 반환합니다.

최종 목표는 Value (하루에 로그인 한 사용자 수)와 Day (해당 날짜)를 포함하는 객체 목록을 갖는 것입니다.

이견있는 사람?

쿼리를 다음으로 변경하면 :

    context.Users
            .Where((x.LastLogIn  >= lastWeek)    
                && (x.LastLogIn <= DateTime.Now))
            .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))
            .Select(x => new
            {
                Value = x.Count(),
                Day = (DateTime)x.Key
            }).ToList();

이제는 하나의 항목이있는 목록을 반환합니다. 여기서 값은 where 절과 일치하는 총 사용자 수이고 그날은 첫날입니다. 아직까지 그룹화 할 수 없었던 것 같습니다.

노트:위의 코드가 옳다는 것을 알았습니다. 나는 다른 것을 잘못하고있었습니다.

그것을 생성하는 SQL은 (예 : 여기에 나와있는 예제와 함께 아주 약간의 구문 오류가있을 수 있습니다.)

SELECT 
1 AS [C1], 
[GroupBy1].[A1] AS [C2], 
 CAST( [GroupBy1].[K1] AS datetime2) AS [C3]
FROM ( SELECT 
        [Filter1].[K1] AS [K1], 
        COUNT([Filter1].[A1]) AS [A1]
        FROM ( SELECT 
                 convert (datetime2, convert(varchar(255), [Extent1].[LastLogIn], 102) ,  102) AS [K1], 
                1 AS [A1]
                FROM [dbo].[Users] AS [Extent1]
                WHERE (([Extent1].[LastLogIn] >= @p__linq__1) AND ([Extent1].[LastLogIn] <= @p__linq__2)
        )  AS [Filter1]
       GROUP BY [K1]
)  AS [GroupBy1] 


  • 쿼리가 정상적으로 보입니다. 당신이 대체 할 때 다시 0이 아닌 값을 얻습니까?GroupBy똑바로Count()? - dasblinkenlight
  • 연속 카운트로 실행하면 where 절과 일치하는 예상 카운트가 반환되고, 이는 그룹을 죽이는 것으로 보입니다 - Thewads
  • 너 대체 했니?Day = (DateTime)EntityFunctions.TruncateTime(x.Key)Day = x.Key? 날짜가 그룹화를 위해 이미 잘 렸기 때문에 동일해야합니다. - dasblinkenlight
  • 좋아, 그것을 제거하면 일부 항목이 변경되어 이제는 단일 항목이있는 목록이 반환됩니다. 세부 사항으로 질문을 업데이트 할 것입니다. - Thewads
  • 바깥 쪽에서 이것은 EF의 버그처럼 보입니다. SQL을 캡처하고 DB에서 직접 실행하여 어떤 일이 일어나는지보십시오. - dasblinkenlight

4 답변


26

두 번째는 필요 없습니다.TruncateTime거기에:

context.Users
    .Where((x.LastLogIn  >= lastWeek) && (x.LastLogIn <= DateTime.Now))
    .GroupBy(x => DbFunctions.TruncateTime(x.LastLogIn))
    .Select(x => new
    {
        Value = x.Count(),
        // Replace the commented line
        //Day = (DateTime)DbFunctions.TruncateTime(x.Key)
        // ...with this line
        Day = (DateTime)x.Key
    }).ToList();

그만큼GroupBy시간이DateTime이미 다시 전화 할 필요가 없습니다.

쓰다DbFunctions.TruncateTime어셈블리를 참조해야합니다.System.Data.Entity포함using System.Data.Entity;

노트 :비추천에 대한 수정 사항EntityFunctions.


  • .GroupBy(x => EntityFunctions.TruncateTime(x.LastLogIn))날짜 별 그룹화를 고려할 때 중요한 요소입니다. - sandeep talabathula
  • @ dasblinkenlight 안녕하세요, count = 0 일을 포함하도록 솔루션에서 변경해야하는 것은 무엇입니까? 로그인이없는 경우에도 시간대에 모든 요일을 반환해야합니다. 감사. - Patrick
  • @ 패트릭 당신이 할 수 있다고 생각하지 않습니다. LINQ는 데이터베이스에없는 경우 결과를 반환하지 않습니다. 결과를 사전으로 변환 한 다음 날짜 범위를 한 번에 하나씩 검토하고 사용할 수있는 경우 사전에서 데이터를 가져올 수 있습니다. - dasblinkenlight
  • @ dasblinkenlight oohhh :( 감사합니다, 감사합니다. - Patrick

2

이 시도:

 .GroupBy(x => new {Year = x.LastLogIn.Year, Month = x.LastLogIn.Month, Day = x.LastLogIn.Day)
                .Select(x => new
                {
                    Value = x.Count(),
                    Year = x.Key.Year,
                    Month = x.Key.Month,
                    Day = x.Key.Day
                })


  • 이봐 요, 이것은 위에서 설명한 것과 같은 상황입니다. 모든 항목의 개수가있는 단일 항목으로 목록을 반환합니다. - Thewads
  • (비록 다소 불쾌하지만) 작동하지만 원래의 쿼리가 작동하지 않는 이유는 무엇입니까? - Alireza

1

당신은 쉽게 할 수 있습니다 :

yourDateList.GroupBy(i => i.ToString("yyyyMMdd"))
             .Select(i => new
             {
                 Date = DateTime.ParseExact(i.Key, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None),
                 Count = i.Count()
             });


  • 그것은 "보인다" 덜 유효합니다. 그러나 나는이 접근법을 여러 번 여러 번 사용해 환상적인 성공을 거두었습니다. 특히, "yyyyMMdd" 데이터를 전달할 때 SQL Server에 대해 일반적으로 허용되는 날짜 형식입니다. - pimbrouwers

1

한 줄로 입력 할 수도 있습니다.

var b = (from a in ctx.Candidates select a)
            .GroupBy(x => x.CreatedTimestamp.Date).Select(g => new { Date=(g.Key).ToShortDateString(), Count = g.Count() });

관련된 질문

최근 질문