How can I get a count by Month from the Linq query below? An error is returned telling me that "grp.INPUT_SOURCE" doesn't exist.
var yesterday = DateTime.Today.AddDays(-365);
var Total = UPDATE_TRANSACTIONS
.Where(m => m.CREATE_DATE > yesterday)
.Where(m => m.CREATE_DATE < DateTime.Today)
.GroupBy(m=> new{m.CREATE_DATE.Value.Year, m.CREATE_DATE.Value.Month,m.CREATE_DATE.Value.Day, m.INPUT_SOURCE})
.Select(grp => new {
source = grp.INPUT_SOURCE,
Count = grp.Count()
});
Total.Dump();
It should be source = grp.Key.INPUT_SOURCE,
since that column is part of the Key
Related
I tried to divided Linq queries into 3 (total, success, fail) but so far "Total" Linq query is working fine. Please help me to get "Success", "Fail" columns (it has mulitple statuses and we have to check the last column of each transaction and destination)
Note: you need to group by ProcessTime, TransactionId, Destination and check last column whether it is success or Fail then apply count (we are using oracle as backend)
LINQ for Total count
var query = (from filetrans in context.FILE_TRANSACTION
join route in context.FILE_ROUTE on filetrans.FILE_TRANID equals route.FILE_TRANID
where
filetrans.PROCESS_STRT_TIME >= fromDateFilter && filetrans.PROCESS_STRT_TIME <= toDateFilter
select new { PROCESS_STRT_TIME = DbFunctions.TruncateTime((DateTime)filetrans.PROCESS_STRT_TIME), filetrans.FILE_TRANID, route.DESTINATION }).
GroupBy(p => new { p.PROCESS_STRT_TIME, p.FILE_TRANID, p.DESTINATION });
var result = query.GroupBy(x => x.Key.PROCESS_STRT_TIME).Select(x => new { x.Key, Count = x.Count() }).ToDictionary(a => a.Key, a => a.Count);
Check this solution. If it gives wrong result, then I need more details.
var fileTransQuery =
from filetrans in context.AFRS_FILE_TRANSACTION
where accountIds.Contains(filetrans.ACNT_ID) &&
filetrans.PROCESS_STRT_TIME >= fromDateFilter && filetrans.PROCESS_STRT_TIME <= toDateFilter
select filetrans;
var routesQuery =
from filetrans in fileTransQuery
join route in context.AFRS_FILE_ROUTE on filetrans.FILE_TRANID equals route.FILE_TRANID
select route;
var lastRouteQuery =
from d in routesQuery.GroupBy(route => new { route.FILE_TRANID, route.DESTINATION })
.Select(g => new
{
g.Key.FILE_TRANID,
g.Key.DESTINATION,
ROUTE_ID = g.Max(x => x.ROUTE_ID)
})
from route in routesQuery
.Where(route => d.FILE_TRANID == route.FILE_TRANID && d.DESTINATION == route.DESTINATION && d.ROUTE_ID == route.ROUTE_ID)
select route;
var recordsQuery =
from filetrans in fileTransQuery
join route in lastRouteQuery on filetrans.FILE_TRANID equals route.FILE_TRANID
select new { filetrans.PROCESS_STRT_TIME, route.CRNT_ROUTE_FILE_STATUS_ID };
var result = recordsQuery
.GroupBy(p => DbFunctions.TruncateTime((DateTime)p.PROCESS_STRT_TIME))
.Select(g => new TrendData
{
TotalCount = g.Sum(x => x.CRNT_ROUTE_FILE_STATUS_ID != 7 && x.CRNT_ROUTE_FILE_STATUS_ID != 8 ? 1 : 0)
SucccessCount = g.Sum(x => x.CRNT_ROUTE_FILE_STATUS_ID == 7 ? 1 : 0),
FailCount = g.Sum(x => failureStatus.Contains(x.CRNT_ROUTE_FILE_STATUS_ID) ? 1 : 0),
Date = g.Min(x => x.PROCESS_STRT_TIME)
})
.OrderBy(x => x.Date)
.ToList();
I am using Xamarin c# linq with sqlite-net pcl (https://github.com/praeclarum/sqlite-net). I found that all my linq groupby cannot be properly translated into SQL. Linq translates the Where clause but not Group By.
In the following example, the fields used in Transaction:
AccountId: int
Amount: double
ICategoryId: int
All these query formats result in SQL without Group By:
select * from "Transaction" where ("DateWithoutTime" <= ?)
var accountBalances1 = _dataService.Connection.Table<Transaction>()
.Where(r => r.DateWithoutTime <= displayDuration.DurationEnd)
.GroupBy(r => r.AccountId)
.Select(g => new
{
Id = g.Key,
Balance = g.Sum(b => b.Amount)
})
.ToList();
var accountBalances2 = _dataService.Connection.Table<Transaction>()
.Where(r => r.DateWithoutTime <= displayDuration.DurationEnd)
.GroupBy(r => r.AccountId,
(key, g) => new
{
Id = key,
Balance = g.Sum(b => b.Amount),
})
.ToList();
var accountBalances3 = (from t in _dataService.Connection.Table<Transaction>()
where t.DateWithoutTime <= displayDuration.DurationEnd
group t by t.AccountId
into g
select new { g.Key, Balance = g.Sum(g => g.Amount) })
.ToList();
To clarify it has nothing to do with double data type, I tried another group by with int data type only:
var maxIECategoryId = _dataService.Connection.Table<Transaction>()
.Where(r => r.DateWithoutTime <= displayDuration.DurationEnd)
.GroupBy(r => r.AccountId,
(key, g) => new
{
Id = key,
IECategoryId = g.Max(b => b.IECategoryId)
})
.ToList();
Similarly, the generated sql does not have group by.
All group by are processed locally. Is there any trick to write a linq group by that can be processed on the server service? or it is a limitation of this implementation of sqlite orm?
Thanks,
Nick
this is LINQ query I have used
var result = (from price in inventoryDb.Pricing.AsNoTracking()
where price.Quantity > 0m
select new
{
TagNo = price.TagNo,
SellingRate = price.SellingRate,
Quantity = price.Quantity
}).ToList();
Based on the Quantity value I need to generate duplicate items in the list.
Output :
result = [0]{TagNo="100", SellingRate=1500.00, Quantity=1}
[1]{TagNo="101", SellingRate=1600.00, Quantity=2}
Expected Result:
result = [0]{TagNo="100", SellingRate=1500.00}
[1]{TagNo="101", SellingRate=1600.00}
[2]{TagNo="101", SellingRate=1600.00}
You can use Enumerable.SelectMany + Enumerable.Range:
var result = inventoryDb.Pricing.AsNoTracking()
.Where(p => p.Quantity > 0m)
.SelectMany(p => Enumerable.Range(0, p.Quantity)
.Select(i => new
{
TagNo = p.TagNo,
SellingRate = p.SellingRate
}))
.ToList();
If that's not supported by your LINQ provider (f.e. Linq-To-Entities), the easiest is to use Linq-To-Objects. To avoid that all is loaded into memory you should use AsEnumerable after the Where:
var result = inventoryDb.Pricing.AsNoTracking()
.Where(p => p.Quantity > 0m)
.AsEnumerable()
.SelectMany(p => Enumerable.Range(0, p.Quantity)
.Select(i => new
{
TagNo = p.TagNo,
SellingRate = p.SellingRate
}))
.ToList();
Keeping with the query syntax just add a Enumerable.Repeat as follows:
var result = (from price in inventoryDb.Pricing.AsNoTracking()
where price.Quantity > 0m
from dup in Enumerable.Repeat(0,price.Quantity)
select new
{
TagNo = price.TagNo,
SellingRate = price.SellingRate,
}).ToList();
If indeed linq to entities does not support then add AsEnumerable like follows:
var result = (from price in inventoryDb.Pricing.AsNoTracking()
.Where(p => p.Quantity > 0m)
.AsEnumerable() //Loads only the filtered items to memory
from dup in Enumerable.Repeat(0,price.Quantity)
select new
{
TagNo = price.TagNo,
SellingRate = price.SellingRate,
}).ToList();
You can also use Enumerable.Range but because you do not use the value of that collection (and in my opinion also just that it describes better what you are doing) I decided just to go with Repeat
How to write a LINQ query to fetch only the boundary records for a condition. For example, Consider the below database table which represents tracking data received from a vehicle:
I wish to fetch only record 47890 and 47880. Which will give the start time and end time when vehicle was stopped.
Right now, in my query i fetch all the records and then take the first and the last. Also, the query need to be generic, I may have multiple stops for a vehicle. For Example:
Stop1 : 11:00 AM to 1:00 PM
Stop2 : 3:00 PM to 3:30 PM
and so on.
Here is the code I have written so far:
var sData = db.Vehicles
.Where(v => v.VehicleId == vehicleId)
.SelectMany(v => v.GsmDeviceLogs)
.Where(gs => gs.DateTimeOfLog > startDate && gs.DateTimeOfLog < endDate && gs.Speed < zeroSpeed && !gs.IgnitionOn)
.Select(v => new
{
DateTimeOfLog = v.DateTimeOfLog,
Location = v.Location
}).OrderBy(gs => gs.DateTimeOfLog).ToList();
The next result is tested with LinqPad. It can be optmized with T-SQL and used via stored procedure.
var indexedRowsAsc = arr.OrderBy(r => r.DateTimeOfLog)
.Select((r, index) => new { Row = r, Index = index});
// find intersection of current row and next row with condition (IgnitionOn)
// intersection can ignore first and last row
var foundRows = (from a in indexedRowsAsc
from b in indexedRowsAsc
where a.Index == (b.Index -1) &&
a.Row.IgnitionOn != b.Row.IgnitionOn
select new {a, b}
).ToArray();
var firstRow = arr.OrderBy(r => r.DateTimeOfLog).FirstOrDefault();
var lastRow = arr.OrderByDescending(r => r.DateTimeOfLog).FirstOrDefault();
// union found rows with first and last row
var distinctFoundRows = foundRows.Select(fr => fr.a.Row)
// comparer can be added for union for proper distinct gathering
.Union(foundRows.Select(fr => fr.b.Row))
// add first and last row
.Union(new Vehicle[]{firstRow})
.Union(new Vehicle[]{lastRow})
.Where(r => r!= null)
.OrderBy(r => r.DateTimeOfLog)
.ToArray();
// find result by grouping rows where IgnitionOn == 0
int groupId = 1;
var result = distinctFoundRows
.Select(row => new {Row =row, GroupId = (row.IgnitionOn == 0? groupId: ++groupId)})
.Where(res => res.Row.IgnitionOn == 0)
.GroupBy(res => res.GroupId)
.Select(gr => new {First = gr.First().Row, Last = gr.Last().Row})
.ToArray();
The secret of finding changed values in column is self joining.
I want to write this simple query with Linq:
select issuercode,securitycode,dataprocessingflag,COUNT(issuercode) as cnt
from cmr_invhdr
where ProcessedLike <> 'STMNT ONLY'
group by issuercode,securitycode,dataprocessingflag
order by Issuercode
I've tried the following code but I get this error( DbExpressionBinding requires an input expression with a collection ResultType.
Parameter name: input) :
var lstCMRInvHdrNips = (from r in e.CMR_INVHDR
where r.ProcessedLike != "STMNT ONLY"
select new {
r.IssuerCode,
r.SecurityCode,
CountofIssuerCode = r.IssuerCode.Count(),
r.DataProcessingFlag
}
).GroupBy(x =>
new {
x.IssuerCode,
x.SecurityCode,
x.DataProcessingFlag,
x.CountofIssuerCode
}
).OrderBy(x => x.Key.IssuerCode).ToList();
Is there any sense to count issuercode while grouping by this field at once? As when groupped by a field, it's COUNT will always be 1.
Probably you should not group by issuercode and count it after the GroupBy in a separate Select statement:
var result = e.CMR_INVHDR
.Where(r => r.ProcessedLike != "STMNT ONLY")
.GroupBy(r => new { r.SecurityCode, r.DataProcessingFlag })
.Select(r => new
{
Value = r.Key,
IssuerCodesCount = r.GroupBy(g => g.IssuerCode).Count()
})
.ToList();