SQL query to LINQ expression - c#

How can I translate this SQL query to a LINQ expression?
select NoteDate, SUM( DurationInHours ) from Note
where IDUser = '2933FB9C-CC61-46DA-916D-57B0D5EF4803' and
NoteDate > '2013-07-01'
group by NoteDate
I tried it, but it didn't work
var lastMonth = DateTime.Today.AddMonths(-1);
var userNotes = GetNotesByUser(idUser);
var b = from note in userNotes
group note by new {note.IDUser, note.NoteDate, note.DurationInHours} into g
where g.Key.NoteDate > lastMonth
select new {g.Key.NoteDate, TotalHours = g.Sum(a => a.DurationInHours)}

var id = new Guid("2933FB9C-CC61-46DA-916D-57B0D5EF4803");
var date = new DateTime(2013, 7, 1);
var query = from n in db.Notes
where n.IDUser == id && n.NoteDate > date
group n by n.NoteDate into g
select new {
NoteDate = g.Key,
Sum = g.Sum(x => x.DurationInHours)
};

Related

Linq between dates

So i have a query that is getting data correctly but as soon as I try to filter out the linq statement with a where between dates, I consistently get zero results.
var query= Enumerable.Empty<CustomClass>().AsQueryable();
query= (from auto in db.AutoInvs
join deal in db.Deals on new { inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT} equals new {inv = deal.INVUID,client = deal.CLIENTID, acct = (int?) deal.ACCOUNT}
join dmCust in db.DMCusts on new {inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT.ToString()} equals new {inv = dmCust.INVUID, client = dmCust.CLIENTID, acct = dmCust.ACCOUNT}
join act in db.Acts on new { inv = auto.INVUID, client = auto.CLIENTID, acct = auto.ACCOUNT.ToString()} equals new { inv = act.INVUID, client = act.CLIENTID, acct = act.Key }
where auto.DATAPROCESSEDDATE == null && auto.INVUID != ""
select new CustomClass()
{
AutoInv = auto,
Deal = deal,
DmCust = dmCust,
Act = act
});
var filteredData = query.Where(c => c.AutoInv.DATESOLD >= dateFrom.Value && c.AutoInv.DATESOLD <= dateTo.Value).AsQueryable();
Console.WriteLine(filteredData.ToList().Count);
Using this stripped down version (and my own data), it works for me:
var query = Enumerable.Empty<Tbl1>().AsQueryable();
DateTime? dateFrom = new DateTime(2017, 5, 10);
DateTime? dateTo = new DateTime(2017, 5, 20);
query = (from auto in db.Tbl1s
select auto);
var filteredData = query.Where(c => c.StartDate >= dateFrom.Value
&& c.StartDate <= dateTo.Value).AsQueryable();
filteredData.Dump();
One possible problem you may be having is that dateTo would be the exclusive end point --- Unless DATESOLD is exactly midnight, you won't get any that are on the end date.

C# lambda-> All rows Select Add Row_Number

I have a table:
DataTable store_temp = new DataTable();
store_temp.Columns.Add("patn");
store_temp.Columns.Add("rf");
store_temp.Columns.Add("name");
store_temp.Columns.Add("conv");
store_temp.Columns.Add("conv_type");
store_temp.Columns.Add("recorddate");
store_temp.Columns.Add("executiondate");
My C# code :
int i = 0;
var rowsgroups = (from row in store_temp.AsEnumerable().GroupBy(row =>
row.Field<string>("patn"))
.OrderBy((g => g.OrderByDescending(y => y.Field<string("executiondate")).ThenByDescending(y =>
y.Field<string>("rf"))))
select new
{
patn = row.ElementAt(i),
rf_num = ++i,
}).ToArray();
I want the lambda experession, which is equivalent to:
select patn, rf,
> row_number() over( partition by patn order by executiondate,rf )
as rf_num,
name, conv,conv_type, recorddate, executiondate
from store_temp2
But, lambda syntax ... var rowsgroups has just a one row..
I want to show all rows in store_temp.
What should I do to fix the query?
row_number() over(partition by patn order by executiondate, rf)
means in LINQ you need to group by patn, then order each group by executiondate, rf, then use the indexed Select overload to get row numbering inside the group, and finally flatten the result with SelectMany.
With that being said, the equivalent LINQ query could be something like this:
var result = store_temp.AsEnumerable()
.GroupBy(e => e.Field<string>("patn"), (key, elements) => elements
.OrderBy(e => e.Field<string>("executiondate"))
.ThenBy(e => e.Field<string>("rf"))
.Select((e, i) => new
{
patn = key,
rf = e.Field<string>("rf"),
rf_num = i + 1,
name = e.Field<string>("name"),
conv = e.Field<string>("conv"),
conv_type = e.Field<string>("conv_type"),
recorddate = e.Field<string>("recorddate"),
executiondate = e.Field<string>("executiondate")
}))
.SelectMany(elements => elements)
.ToArray();
Try something like this
select new
{
rowNum = store_temp.Rows.IndexOf(row),
patn = row.ElementAt(i),
rf_num = ++i,
}).ToArray();
I don't think you required any groupby as per your required sql
var i=0;
var rowsgroups = (from row in store_temp.AsEnumerable()
orderby row.Field<string>("executiondate") descending,
row.Field<string>("rf") descending
select new
{
patn = row.Field<string>("patn"),
rf_num = ++i,
name = row.Field<string>("name"),
conv = row.Field<string>("conv"),
conv_type = row.Field<string>("conv_type"),
recorddate = row.Field<string>("recorddate"),
executiondate = row.Field<string>("executiondate")
}).ToArray();

Get Sum of a field in Linq with Group by

I am having an SQL:
SELECT ApplicationNo,COUNT(ApplicationNo) AS CNT, SUM(Amount) as AMNT
FROM Payments where (TYPE=1 AND Position=1) and (Date>='2011-01-01')
and (Date<='2012-01-01')
GROUP BY ApplicationNo
Is there a way in which I can convert the same in Linq?
var q = (from payments in context.Payments
where payments.Date >= fromdate && payments.Date <= todate
group payments by new { payments.ApplicationId } into g
select new
{
applicationId=g.Key,
Amount=g.Sum(a=>a.Amount)
});
If I write the same in Linq and then Group by in the end, I am not getting the same result.
DateTime fromDate = new DateTime(2011, 1, 1);
DateTime toDate = new DateTime(2011, 1, 1);
var query = from p in db.Payments
where p.Type == 1 && p.Position == 1 &&
p.Date >= fromDate && p.Date <= toDate
group p by p.ApplicationNo into g
select new {
ApplicationNo = g.Key,
CNT = g.Count(),
AMNT = g.Sum(x => x.Amount)
};
Here db is your context class.

This LINQ-to-Entities join seems overly complex, am I doing something wrong?

I have two queries that I need to combine in LINQ that both actually come from the same table. The reason for this is that one of the queries needs to get the max of a field for each day and then sum the days together where the second query can just sum everything right off the bat. Here is the first query:
var queryDownload = from p in
(from p in almdbContext.cl_contact_event
where p.time_of_contact >= startDate && p.time_of_contact < endDate && p.input_file_name.Contains(inputFileName) && listName.Contains(listName)
group p by new
{
date = EntityFunctions.CreateDateTime(p.time_of_contact.Value.Year, p.time_of_contact.Value.Month, p.time_of_contact.Value.Day, 0, 0, 0),
listName = p.contact_list_name
} into g
select new
{
date = g.Key.date,
listName = g.Key.listName,
download = g.Max(a => a.total_number_of_records)
})
group p by p.listName into g
select new
{
listName = g.Key,
totalDownload = g.Sum(a => a.download),
};
This is the second:
var queryPenData = from p in almdbContext.cl_contact_event
where p.time_of_contact >= startDate && p.time_of_contact < endDate && p.input_file_name.Contains(inputFileName) && listName.Contains(listName)
group p by p.contact_list_name into g
select new
{
listName = g.Key,
dials = g.Sum(a => a.ov_dial_start_time != null ? 1 : 0),
agentConnects = g.Sum(a => a.agent_login_name != null ? 1 : 0),
abandons = g.Sum(a => a.response_status == "DAC" || a.response_status == "DAD" ? 1 : 0),
rightPartyContacts = g.Sum(a => a.response_status == "PTP" || a.response_status == "RPC" ? 1 : 0),
promiseToPays = g.Sum(a => a.response_status == "PTP" ? 1 : 0),
talkTime = g.Sum(a => EntityFunctions.DiffSeconds(a.ov_call_connected_time, a.ov_trunk_released_time)) ?? 0,
wrapTime = g.Sum(a => EntityFunctions.DiffSeconds(a.ov_trunk_released_time, a.record_released_time)) ?? 0
};
And this is the query joining them together.
var queryJoin = from qd in queryDownload
join qp in queryPenData
on qd.listName equals qp.listName
select new
{
listName = qp.listName,
download = qd.totalDownload,
dials = qp.dials,
agentConnects = qp.agentConnects,
abandons = qp.abandons,
rightPartyContacts = qp.rightPartyContacts,
promiseToPays = qp.promiseToPays,
talkTime = qp.talkTime,
wrapTime = qp.wrapTime
};
This seems extremely verbose/roundabout to me. Is there a better way I can write/approach this to shrink/simplify the code?
For your last query could you not just do something like this?
var queryJoin = from qd in queryDownload join qpd in queryPenData on qd.listname equals qpd....
Should be able to do this:
var queryJoin = from qd in queryDownload
join qp in queryPenData
on qd.listName equals qp.listName
select new
{
qp, qd
};
From what I can tell you've already formed your data in queryPenData so there is no reason to re-assign it to new variables in the final join. Just select the object which will allow you to traverse into the anonymous type in queryPenData. I think...

LINQ find max/min value with corresponding time fields

I have a table of data recordings from a weather station from which I am querying results into a WPF ListBox.
The table structure is:
date
time
temp
rain_today
humidity
etc
I have a query which works fine:
var q = from c in db.Apr11log
group c by c.LogDate into g
orderby g.Key
select new
{
LogDate = g.Key,
MaxTemp = g.Max(c => c.Temp),
MinTemp = g.Min(c => c.Temp),
Rain = g.Max(c => c.Rain_today),
};
However I am trying to get the corresponding time of the Max Temp and Min Temp, i.e.
TimeMax = .....
TimeMin = .....
I've googled and googled but found nothing useful.
var q = from c in db.Apr11log
group c by c.LogDate into g
orderby g.Key
select new
{
LogDate = g.Key,
MaxRow = g.OrderByDescending(c => c.Temp).Select(c => new { c.LogDate, c.Temp }).First(),
MinRow = g.OrderBy(c => c.Temp).Select(c => new { c.LogDate, c.Temp }).First(),
Rain = g.Max(c => c.Rain_today),
};
or
var q = from c in db.Apr11log
group c by c.LogDate into g
orderby g.Key
let maxRow = g.OrderByDescending(c => c.Temp).First()
let minRow = g.OrderBy(c => c.Temp).First()
select new
{
LogDate = g.Key,
MaxTemp = maxRow.Temp,
MaxTempDate = maxRow.LogDate,
MinTemp = minRow.Temp,
MinTempDate = minRow.LogDate,
Rain = g.Max(c => c.Rain_today),
};
let maxTemp = c.Max(c=>c.Temp)
let minTemp = c.Min(c=>c.Temp)
select new {
LogDate = g.Key,
MaxTemp = maxTemp,
MinTemp = minTemp,
MaxTime = g.FirstOrDefault(c=>c.Temp = maxTemp).Time,
MinTime = g.FirstOrDefault(c => c.Temp = minTemp).Time,
Rain = g.Max(c => c.Rain_today),
};

Categories