0

我试图在不同设备上获取我的应用程序过去 30 天的总下载次数,我成功地返回了正确的查询,方法是按天数分组并与过去 30 天的可枚举连接。但是我无法根据需要格式化输出。让我先用 LinqPad 中的演示文稿分享查询

var last_days = (from idx in Enumerable.Range(1, (DateTime.Now - DateTime.Now.AddDays(-30)).Days)
select new { day = DateTime.Now.AddDays(-30).AddDays(idx).Date});

var orders = (from od in Orders
group od by EntityFunctions.AddSeconds((DateTime?)new DateTime(1970,1,1,0,0,0,0), (int?)od.Created) into g
select new { 
    day = g.Key ,
    web = g.Where( q => q.Source == "web").Count(),
    ios = g.Where( q => q.Source == "ios").Count(),
    android = g.Where( q => q.Source == "android").Count(),
    total = g.Count()
}).OrderByDescending(q => q.day).Take(31);

var days= 
(from d in last_days
join od in orders on d.day equals od.day into x
from od in x.DefaultIfEmpty()
select x );

days.Dump();

这是我得到的结果

在此处输入图像描述

现在,我想将最终输出格式化为 5 列(day、web、ios、android、total)的 IEnumerable,无论它是否为空。因此,我得到的不是空的 O 符号,而是日期和 web = ios = android = total = 0。我该怎么做?所以在没有任何下载的日子里,我仍然得到一个日期和平台为 0 的条目。

4

3 回答 3

2

这几乎不是最优雅的解决方案,但这样的事情应该可以工作:

var days = last_days.Select(d =>
  orders.DefaultIfEmpty(new {
    day = d,
    web = 0,
    ios = 0,
    android = 0,
    total = 0
  }).FirstOrDefault(od =>
    od.day == d.Date));

基本思想是告诉生成器,在每种情况下,如果找不到合适的订单条目,该依靠什么。


回想起来,从一张白纸开始可能更容易。更像是什么:

var last_30_days =
  from idx in Enumerable.Range(1, 30)
  orderby idx descending
  select DateTime.Now.AddDays(idx - 30).Date;

var orders =
  from date in last_30_days
  let datesOrders = Orders.Where(order => order.Created == date)
  select new Info()
  {
    Date = date,
    Web = datesOrders.Where(q => q.Source == "web").Count(),
    iOS = datesOrders.Where(q => q.Source == "ios").Count(),
    Android = datesOrders.Where(q => q.Source == "android").Count(),
    Total = datesOrders.Count()
  };
于 2013-07-19T17:13:29.517 回答
0

选择 new DaySum { ord = (ord == null ? 0 : ord.Count) };

而不仅仅是

选择 x

于 2013-07-19T17:07:33.940 回答
0

做对了,生成的 sql 在复杂度上还可以,我猜在 linq 上有点生疏

var last_days = (from idx in Enumerable.Range(1, (DateTime.Now - DateTime.Now.AddDays(-31)).Days)
select new { day = DateTime.Now.AddDays(-31).AddDays(idx).Date});

var orders = (from od in Orders
where od.ServiceProviderID == 2
group od by new DateTime(1970,1,1,0,0,0,0).AddSeconds(od.Created).Date into g
select new { 
    day = (DateTime)g.Key ,
    web = g.Where( q => q.Source == "web").Count(),
    ios = g.Where( q => q.Source == "ios").Count(),
    android = g.Where( q => q.Source == "android").Count(),
    total = g.Count()
}).OrderByDescending(q => q.day).Take(32);

var days = (from d in last_days
join od in orders on d.day.Date equals od.day.Date into x
from od in x.DefaultIfEmpty()
select new { 
    day = d.day ,
    web = (od == null) ? 0: od.web,
    ios = (od == null) ? 0: od.ios,
    android = (od == null) ? 0: od.android,
    total = (od == null) ? 0 : od.total
    } );

days.Dump();
于 2013-07-19T20:24:41.667 回答