2013-07-19 2 views
0

Я пытаюсь получить общее количество загрузок моего приложения за последние 30 дней на разных устройствах, мне удалось вернуть правильный запрос, группируя по количеству дней и присоединяясь к перечислимому с помощью последние тридцать дней. Однако я не могу отформатировать вывод так, как хочу. Поделится запрос первым с презентацией в LINQPadLinq DefaultValues ​​on Join

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(); 

Это результат я получаю

enter image description here

Теперь я хочу, чтобы отформатировать окончательный вывод в IEnumerable 5 колонка (день , web, ios, android, total) независимо от того, был ли он пустым или нет. Поэтому вместо пустой знака O я получаю дату, а web = ios = android = total = 0. Как я могу это сделать? Итак, в день без каких-либо загрузок я до сих пор получаю запись с датой и платформами на 0.

ответ

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(); 
0

Как насчет выбора нового DaySum {ord = (ord == null? 0: ord.Count)};

Вместо всего

Выберите х

+0

СММ что является объектом DaySum? –

+0

Вы можете назвать эти анонимные типы. DaySum - это мое представление о том, какова каждая строка этой коллекции, ежедневное резюме. –

+0

Хм, я думаю, вам нужно сначала объявить этот класс. Я думаю, что это то, с чем я столкнулся, пытаясь объявить тип возвращаемого значения функции анонимным типом. –

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() 
    }; 
+0

Я получил этот errpr _'System.Linq.IQueryable 'не содержит определения для' DefaultIfEmpty 'и лучший метод перегрузки расширения' System.Linq.ParallelEnumerable.DefaultIfEmpty (System.Linq.ParallelQuery , TSource) 'имеет некоторые недопустимые аргументы Аргумент экземпляра: не может преобразовать из' System.Linq.IQueryable 'в' System.Linq.ParallelQuery '_ в части заказов. Если я удалю выражение lamma DefaultIfEmpty, я получаю то, что имел в виду, но теперь запрос занимает 10 секунд, а сгенерированный sql - 1400 строк. –

+0

Ну, я думаю, это было бы довольно убедительным аргументом в пользу того, что эти запросы не отвечают анонимными типами. Вы пытались сделать простую структуру для хранения хитов? –

+0

В любом случае, я переосмыслил свой ответ в своем правлении выше. –