我想创建一个Linq查询,用于比较单个表中多行的日期。 该表包含轮询Web服务以获取帐户余额数据的数据。不幸的是,轮询间隔不是100%确定性,这意味着每个帐户每天可以有0-1个条目。
对于应用程序,我需要以某种格式重新格式化这些数据(参见下面的输出)。 我包括了样本数据和表格的描述。
任何人都可以帮我处理能产生所需输出的EF Linq查询吗?
表:
id The account id balance The available credits in the account at the time of the measurement create_date The datetime when the data was retrieved
表名:余额
字段:id(int)
领域:平衡(bigint)
字段:create_date(datetime)
样本数据:
id balance create_date 3 40 2012-04-02 07:01:00.627 1 55 2012-04-02 13:41:50.427 2 9 2012-04-02 03:41:50.727 1 40 2012-04-02 16:21:50.027 1 49 2012-04-02 16:55:50.127 1 74 2012-04-02 23:41:50.627 1 90 2012-04-02 23:44:50.427 3 3 2012-04-02 23:51:50.827 3 -10 2012-04-03 07:01:00.627 1 0 2012-04-03 13:41:50.427 2 999 2012-04-03 03:41:50.727 1 50 2012-04-03 15:21:50.027 1 49 2012-04-03 16:55:50.127 1 74 2012-04-03 23:41:50.627 2 -10 2012-04-03 07:41:50.727 1 100 2012-04-03 23:44:50.427 3 0 2012-04-03 23:51:50.827
预期产量:
id 帐户ID
日期 用于在行中生成日期的数据组件
balance_last_measurement 最后一次测量日期的余额
差异 日期的第一次和最后一次测量之间的平衡差异
id date balance_last_measurement difference 1 2012-04-02 90 35 1 2012-04-03 100 10 2 2012-04-02 9 9 2 2012-04-03 -10 -19 3 2012-04-02 3 -37 3 2012-04-03 0 37
RaphaëlAlthaus的回答非常好,但我确实在原始请求中犯了一个小错误。 “预期产出”中的差异字段应为:
这有可能吗?这似乎很复杂?
答案 0 :(得分:1)
我会尝试这样的事情。
var query = db.Balances
.OrderBy(m => m.Id)
.ThenBy(m => m.CreationDate)
.GroupBy(m => new
{
id = m.Id,
year = SqlFunctions.DatePart("mm", m.CreationDate),
month = SqlFunctions.DatePart("dd", m.CreationDate),
day = SqlFunctions.DatePart("yyyy", m.CreationDate)
}).ToList()//enumerate there, this is what we need from db
.Select(g => new
{
id = g.Key.id,
date = new DateTime(g.Key.year, g.Key.month, g.Key.day),
last_balance = g.Select(m => m.BalanceValue).LastOrDefault(),
difference = (g.Count() == 1 ? g.First().BalanceValue : g.Last().BalanceValue - g.First().BalanceValue)
});
答案 1 :(得分:0)
嗯,一个可能没有优化的解决方案,但只是看看它是否有效。
首先,我们创建一个结果类
public class BalanceResult
{
public int Id { get; set; }
public DateTime CreationDate { get; set; }
public IList<int> BalanceResults { get; set; }
public int Difference { get; set; }
public int LastBalanecResultOfDay {get { return BalanceResults.Last(); }}
public bool HasManyResults {get { return BalanceResults != null && BalanceResults.Count > 1; }}
public int DailyDifference { get { return HasManyResults ? BalanceResults.Last() - BalanceResults.First() : BalanceResults.First(); } }
}
然后我们改变了一点我们的查询
var query = db.Balances
.GroupBy(m => new
{
id = m.Id,
year = SqlFunctions.DatePart("mm", m.CreationDate),
month = SqlFunctions.DatePart("dd", m.CreationDate),
day = SqlFunctions.DatePart("yyyy", m.CreationDate)
}).ToList()//enumerate there, this is what we need from db
.Select(g => new BalanceResult
{
Id = g.Key.id,
CreationDate = new DateTime(g.Key.year, g.Key.month, g.Key.day),
BalanceResults = g.OrderBy(l => l.CreationDate).Select(l => l.BalanceValue).ToList()
}).ToList();
最后
foreach (var balanceResult in balanceResults.ToList())
{
var previousDayBalanceResult = balanceResults.FirstOrDefault(m => m.Id == balanceResult.Id && m.CreationDate == balanceResult.CreationDate.AddDays(-1));
balanceResult.Difference = previousDayBalanceResult != null ? balanceResult.LastBalanecResultOfDay - previousDayBalanceResult.LastBalanecResultOfDay : balanceResult.DailyDifference;
}
如所示,性能(例如使用字典),代码可读性当然应该得到改善,但......这就是想法!