現在、選択した日付で結果をグループ化するクエリを実行したいという問題に取り組んでいます。
この例では、次のような単純なモデルを想像してください。
public class User
{
public DateTime LastLogIn {get; set;}
public string Name {get; set;}
}
私が探している解決策は、日付ごとにログインしているユーザーの数を取得することです。データベースでは、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();
ただし、上記は空のリストを返します。
最終目標は、値(1日にログインしたユーザーの数)と1日(問題の日)を含むオブジェクトのリストを持つことです。
何かご意見は?
クエリを次のように変更すると:
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();
現在は、単一のアイテムを含むリストを返します。Valueはwhere句に一致するユーザーの総数であり、Dayは最初の日です。まだ日ごとにグループ化することができないようです
注:上記のコードが正しいことがわかりました。私は何か他のことを間違っていました。
それが生成している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]
2番目の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 => 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
})
簡単にできます:
yourDateList.GroupBy(i => i.ToString("yyyyMMdd"))
.Select(i => new
{
Date = DateTime.ParseExact(i.Key, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None),
Count = i.Count()
});
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() });