Hi i have a datatable with following fields
DAT_START
GROUPBY
TXT_LATITTUDE
TXT_LONGITUDE
INT_DIRECTION
INT_CALL_DATA_TYPE
LNG_DURATION
And following is the LINQ query i am using
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);
It gives me result like this
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
Now i want result like this
CellID = 4057, TotalCommCount = 204, TotalDuration = 147, INSMSCount = 56,OutSMSCount = 41, INVoiceCount = 84,OutVoiceCount = 8,InVoiceDuration =50,OutVoiceDuration = 47
How can i do this. I am struck over here..
It looks like you're grouping by far too much at the moment, which is why you're getting multiple rows. I suspect you want something like this:
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;
I suggest you create a view in your SQL database where you can simply aggregate what you need and then you use that view in your Linq query - this will perform fast and it is easy to write.
Sketch of design:
Since the description of your requirements is not totally clear, I have made assumptions. Create a SQL view such as (it's just to show the idea, change it according to your needs):
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
(You know you can easily add this view to your *.EDMX by using "update model from database" in the context menu of the entity diagram page and then tick-mark the view vSumDurations in the "tables/views" section of the dialog which pops up.)
After this preparation your Linq query is very simple because everything is already done in the view. Hence, the code looks like:
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();
Note: The example is made for LinqPad - you will need a different data context in your real code. Linqpad does not need dc
, but it is easier if you declare it for convenience reasons because in your real code you have to provide it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.