2013-05-14 2 views
0

Привет У меня есть DataTable со следующими полямиКак написать этот LINQ запрос

DAT_START 
GROUPBY 
TXT_LATITTUDE 
TXT_LONGITUDE 
INT_DIRECTION 
INT_CALL_DATA_TYPE 
LNG_DURATION 

И следующим является запрос LINQ Я использую

var data = (from r in dt.AsEnumerable() 
where ((r.Field<DateTime>("DAT_START").TimeOfDay.Hours < 20) && (r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= 4)) 
group r by new { CID = r["GroupBy"], CLatitude = r["TXT_LATITUDE"], CLongitude = r["TXT_LONGITUDE"],CDirection = r["INT_DIRECTION"], 
CCallType = r["INT_CALL_DATA_TYPE"],CDuration = r["LNG_DURATION"] } 
into groupedTable 
select new 
{ 
    CellID = groupedTable.Key.CID, 
    CallCount = groupedTable.Count(), 
    Longitude = groupedTable.Key.CLongitude, 
    Latitude = groupedTable.Key.CLatitude, 
    Direction = groupedTable.Key.CDirection, 
    CallType = groupedTable.Key.CCallType, 
    Duration = groupedTable.Key.CDuration 
}).OrderByDescending(s => s.CallCount); 

Это дает мне результат, как это

CellID = 4057,CallCount = 84,Longitude = "",Latitude = "",Direction = "Incoming",CallType = "Voice",Duration = 50 
CellID = 4057,CallCount = 8,Longitude = "",Latitude = "",Direction = "Outgoing",CallType = "Voice",Duration =97 
CellID = 4057,CallCount = 56,Longitude = "",Latitude = "",Direction = "Incoming",CallType ="SMS" ,Duration = 0 
CellID = 4057,CallCount = 41,Longitude = "",Latitude = "",Direction = "Outgoing",CallType = "SMS",Duration = 0 

Теперь я хочу получить результат следующим образом

CellID = 4057, TotalCommCount = 204, TotalDuration = 147, INSMSCount = 56,OutSMSCount = 41, INVoiceCount = 84,OutVoiceCount = 8,InVoiceDuration =50,OutVoiceDuration = 47 

Как я могу это сделать. Я поражен здесь.

+0

Не уверен, но вы не можете сделать дополнительную группу по «CellID», а затем суммировать другие столбцы? – Habib

+0

Вы пытались сделать это с помощью SQL !? Это будет намного проще, как вы используете DataTable, зачем делать такую ​​грязную работу внутри кода? – IamStalker

+0

@Habib Мне нужно получить сумму всех 'Duration', а также сумму' duration' группы 'Direction' и' CallType'. –

ответ

6

Похоже, вы группируете слишком много на данный момент, поэтому вы получаете несколько строк. Я подозреваю, что вы хотите что-то вроде этого:

from r in dt.AsEnumerable() 
where r.Field<DateTime>("DAT_START").TimeOfDay.Hours < 20 && 
     r.Field<DateTime>("DAT_START").TimeOfDay.Hours >= 4 
group r r["GroupBy"] into g   
select new 
{ 
    CellID = g.Key, 
    TotalCommCount = g.Count(), 
    TotalDuration = g.Sum(r => r.Field<long>("LNG_DURATION")), 
    InSMSCount = g.Count(r => r.Field<string>("DIRECTION") == "Incoming" && 
           r.Field<string>("CALL_TYPE") == "SMS"), 
    OutSMSCount = g.Count(r => r.Field<string>("DIRECTION") == "Outgoing" && 
           r.Field<string>("CALL_TYPE") == "SMS"), 
    InVoiceCount = g.Count(r => r.Field<string>("DIRECTION") == "Incoming" && 
           r.Field<string>("CALL_TYPE") == "Voice"), 
    OutVoiceCount = g.Count(r => r.Field<string>("DIRECTION") == "Outgoing" && 
           r.Field<string>("CALL_TYPE") == "Voice"), 
    InVoiceDuration = g.Where(r => r.Field<string>("DIRECTION") == "Incoming" && 
           r.Field<string>("CALL_TYPE") == "Voice") 
         .Sum(r => r.Field<long>("DURATION")) 
    OutVoiceDuration = g.Where(r => r.Field<string>("DIRECTION") == "Outgoing" && 
            r.Field<string>("CALL_TYPE") == "Voice"), 
         .Sum(r => r.Field<long>("DURATION")) 
} into summary 
order by summary.TotalCommCount descending 
select summary; 
+0

Спасибо, Джон, он работает. У меня были некоторые проблемы с данными. –

0

Я предлагаю вам создать представление в базе данных SQL, где вы можете просто агрегировать, что вам нужно, и затем использовать эту точку зрения в запросе Linq - это будет работать быстро и его легко писать.

Эскиз дизайна:

Поскольку описание ваших требований не совсем понятно, я сделал предположения. Создать вид SQL, такие как (это просто, чтобы показать идею, изменить его в соответствии с вашими потребностями):

CREATE VIEW [dbo].[vSumDurations] 
AS 
select c.CellId, j1.SumDuration1 as TotalDuration, 
     j2.SumDuration2 as GroupedDuration, j1.CallCount 
from (select distinct t.CID as CellId from [dbo].[YourTable] t) c 
left join (select t1.CID as CellId, sum(LNG_Duration) as SumDuration1, 
      count(*) as CallCount from [dbo].[YourTable] t1 
      Group By t1.CID) j1 
on c.CellId=j1.CellId   
left join (select t2.CID as CellId, sum(LNG_Duration) as SumDuration2 
      from [dbo].[YourTable] t2 
      Group by t2.CID, t2.Direction, t2.CallType) j2 
on c.CellId=j2.CellId 

(Вы знаете, вы можете легко добавить эту точку зрения на ваш * EDMX-с помощью «обновление модель из базы данных»в контекстном меню страницы объекта диаграммы, а затем клещевой отметьте вид vSumDurations в„разделе таблицы/виды“диалоговое окно, которое выскакивает.)

После этого препарата вашего Linq запрос является очень просто, потому что все уже сделано в представлении. Таким образом, код выглядит следующим образом:

var dc = this; // in LinqPad you can set your data context 
var data = (from d in dc.vSumDurations select d).OrderByDescending(s => s.CallCount); 
data.Dump(); 

Примечание: пример сделан для LinqPad - вам нужен другой контекст данных в вашем реальном коде. Linqpad не нужен dc, но это проще, если вы объявите его по соображениям удобства, потому что в вашем реальном коде вы должны его предоставить.

Смежные вопросы