I've had a look through StackOverflow and have tried things from a few posts but am totally stuck. Basically I have the query below (tested in LinqPad), which, for the "sum" values gives me the same value twice. What I actually want is a join to the same table, group by date and to show the sum of what is essentially the same column (Value), from the joined table and the original table.
I have found that you can't use aliases (i.e. in SQL FieldName as 'NewFieldName') in LINQ, so somehow I need to sum up t.Value and p.Value, and show those next to SiteID and EntryDate in my results.
(from p in DailyStatistics
join t in DailyStatistics on new { p.EntryDate, p.SiteID} equals new { t.EntryDate, t.SiteID}
where t.Metric == "MyVisitors"
&& p.Metric == "MyVisits"
&& p.EntryDate >= DateTime.Parse("2013-08-15" )
&& p.EntryDate <= DateTime.Parse("2013-08-21" )
group p by new { t.SiteID, p.EntryDate } into s
orderby s.Key.EntryDate
select new {s.Key.SiteID, s.Key.EntryDate, SumVisits = s.Sum(t => t.Value), SumVisitors = s.Sum(x => x.Value) })
This one in particular I tried, but couldn't quite adapt it to my needs:
SQL multiple joins and sums on same table
Any ideas would be happily accepted :-)
Edit
I forgot the where clause.
DailyStatistics
.Join
(
DailyStatistics,
x=>new{x.EntryDate, x.SiteID},
x=>new{x.EntryDate, x.SiteID},
(o,i)=>new
{
VisitorEntry=i.Metric,
VisitEntry=o.Metric,
VisitorDate = i.EntryDate ,
VisitDate = o.EntryDate ,
i.SiteID,
VisitorValue = i.Value,
VisitValue = o.Value
}
)
.GroupBy
(
x=>
new
{
x.SiteID,
x.VisitDate
}
)
.Where
(
x=>
x.VisitorEntry == "MyVisitors" &&
x.VisitEntry== "MyVisits" &&
x.VisitDate >= DateTime.Parse("2013-08-15") &&
x.VisitDate <= DateTime.Parse("2013-08-21")
)
.Select
(
x=>
new
{
x.Key.SiteID,
x.Key.VisitDate,
SumVisits = s.Sum(t => t.VisitValue ),
SumVisitors = s.Sum(x => x.VisitorValue )
}
)
.OrderBy
(
x=>x.VisitDate
)
Related
I have multiple customers that are a part of a group designated by a group id.
I would like to retrieve 1 record from a related table for each of the matching group members (last record before a certain date).
Currently I query for a list of group members then for each member i run another query to retrieve last record from a date.
I would like to do this with one query since i can pull up the associated table records using group id - however this returns all the records associated to group (bad).
If i use first or default i only get results for first group found.
I want 1 record from each group member.
My Code (returns all associated records of group members):
List<Record> rs = (from x in db.Records where (x.Customer.Group == udcg && x.CloseDate < date && x.CloseDate < earlyDate) orderby x.CloseDate descending select x).ToList();
But i just want one from each instead of all.
Code I use now:
var custs = (from x in db.Customers where (x.group == udcg) select new { x.CustomerID }).ToList();
expected = custs.Count();
foreach (var cust in custs)
{
Record br = (from x in db.Records where (x.Customer.CustomerID == cust.CustomerID && x.CloseDate < date && x.CloseDate < earlyDate)) orderby x.CloseDate descending select x).FirstOrDefault();
if (br != null)
{
total = (double)br.BillTotal;
cnt++;
}
}
I think this could work
db.Customers
.Where(c => c.group == udcg)
.Select(c => db.Records
.Where(r => r.Customer.CustomerID == c.CustomerID)
.Where(r => r.CloseDate < date)
.Where(r => r.CloseDate > date.AddMonths(-2))
.OrderByDescending(r => r.CloseDate)
.FirstOrDefault())
.Where(r => r != null)
It is translated into one sql query. That means it uses one roundtrip to the server. That could be quite a big difference in performace when compared to the foreach loop. If you look at the generated sql, it would be something like
SELECT some columns
FROM Customers
OUTER APPLY (
SELECT TOP (1) some columns
FROM Records
WHERE some conditions
ORDER BY CloseData DESC
)
In terms of performace of the query itself, I would not expect problems here, sql server should not have problems optimizing this form (compared to other ways you could write this query).
Please try this one, evaluate records list.
DateTime certain_date = new DateTime(2018, 11, 1);
List<Record> records = new List<Record>();
var query = records.GroupBy(x => x.Customer.Group).Select(g => new { Group = g.Key, LastRecordBeforeCertainDate = g.Where(l => l.CloseDate < certain_date).OrderByDescending(l => l.CloseDate).FirstOrDefault() });
I'm developing on visual Studio using asp.net core and Entity Framework.
This is my query
var Male = from s in _context.ApprovalKits
join r in _context.Registrations on s.StundetId equals r.StundetId into a
where s.RoomType.Equals(RoomType.s)
&& s.HealthCondition.Equals(HealthCondition.none)
&& r.gender.Equals(Gender.m)
select a;
There is an error on the r.gender:
The name 'r' does not exist in the current context
How can I fix my query?
If your EF Entities have Associations set-up correctly then you should never need to use manual Joins in Linq because you can simply do this:
List<Registration> maleRegistrations = db.Registrations
.Include( r => r.ApprovalKit )
.Where( r => r.ApprovalKit.RoomType == RoomType.S )
.Where( r => r.HealthCondition == HealthCondition.None )
.Where( r => r.Gender == Gender.Male );
.ToList();
(You can also consolidate the Where, like so:)
List<Registration> maleRegistrations = db.Registrations
.Include( r => r.ApprovalKit )
.Where( r =>
r.ApprovalKit.RoomType == RoomType.S &&
r.HealthCondition == HealthCondition.None &&
r.Gender == Gender.Male
)
.ToList();
I am trying to get articles by publishers who are members or employees and trying to use the following query:
var articles = context.articles
.Include("Article")
.Include("ArticleType")
.Include("Language")
.Join(
context.publishers
, cb => cb.publisher_id.ToString()
, ct => ct.id
, (cb, ct) =>
new
{
articles = cb
,
publishers = ct
}
)
.Where(
c.articles.active != null &&
c.articles.active.Value &&
(
(c.publishers.PublisherTypeId == (int)Utility.PublisherTypes.MEMBERS)
||
(c.publishers.PublisherTypeId == (int)Utility.PublisherTypes.EMPLOYEES)
)
)
.Select(joined => joined.articles)
.ToList();
articles has a publisher_id that is a guid but publisher has a id that is a string (I did not design the database but to me this looks wrong and should be re designed).
Somehow when joining publishers no records are returned; the list is empty. I do not know why this would be since there are articles published
How I will convert this SQL query in Linq, sorry but I am not that much expert in LINQ
select ConnectionId
from LearnerConnections
where LearnerId = 1
union
select LearnerId
from LearnerConnections
where ConnectionId = 1
also can I write the DataTable methode to get the result (like DataTable.Select() method)?
thanks in advance
something like that
LearnerConnections.Where(x => x.LearnerId == 1)
.Select(m => m.ConnectionId)
.Union(LearnerConnections.Where(l => l.ConnectionId ==1)
.Select(lc => lc.LearnerId)
);
with a datatable, it should look like
dtLearnerConnections.AsEnumerable()
.Where(m => m.Field<int>("LearnerId") == 1)
.Select(m => m.Field<int>("ConnectionId"))
.Union(dtLearnerConnections.AsEnumerable()
.Where(x => x.Field<int>("ConnectionId") == 1)
.Select(x => x.Field<int>("LearnerId"))
);
May this will helpful
var results = (from l in LearnerConnections where l.LearnerId == 1
select l.ConnectionId).Union(from a in LearnerConnections
where a.ConnectionId == 1 select l.LeaenerId);
var result = (from lc in LearnerConnections
where lc.LearnerId == 1
select lc.ConnectionId)
.Union
(from lc in LearnerConnections
where lc.ConnectionId == 1
select lc.LearnerId);
If you are using DataTables, this involves the use of LINQ to DataSet. This SO question might also help you.
I'm using LINQ on an IQueryable returned from NHibernate and I need to select the row with the maximum value(s) in a couple of fields.
I've simplified the bit that I'm sticking on. I need to select the one row from my table with the maximum value in one field.
var table = new Table { new Row(id: 1, status: 10), new Row(id: 2, status: 20) }
from u in table
group u by 1 into g
where u.Status == g.Max(u => u.Status)
select u
This is incorrect but I can't work out the right form.
BTW, what I'm actually trying to achieve is approximately this:
var clientAddress = this.repository.GetAll()
.GroupBy(a => a)
.SelectMany(
g =>
g.Where(
a =>
a.Reference == clientReference &&
a.Status == ClientStatus.Live &&
a.AddressReference == g.Max(x => x.AddressReference) &&
a.StartDate == g.Max(x => x.StartDate)))
.SingleOrDefault();
I started with the above lambda but I've been using LINQPad to try and work out the syntax for selecting the Max().
UPDATE
Removing the GroupBy was key.
var all = this.repository.GetAll();
var address = all
.Where(
a =>
a.Reference == clientReference &&
a.Status == ClientStatus.Live &&
a.StartDate == all.Max(x => x.StartDate) &&
a.AddressReference == all.Max(x => x.AddressReference))
.SingleOrDefault();
I don't see why you are grouping here.
Try this:
var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);
An alternate approach that would iterate table only once would be this:
var result = table.OrderByDescending(x => x.Status).First();
This is helpful if table is an IEnumerable<T> that is not present in memory or that is calculated on the fly.
You can also do:
(from u in table
orderby u.Status descending
select u).Take(1);
You can group by status and select a row from the largest group:
table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();
The first First() gets the first group (the set of rows with the largest status); the second First() gets the first row in that group.
If the status is always unqiue, you can replace the second First() with Single().
Addressing the first question, if you need to take several rows grouped by certain criteria with the other column with max value you can do something like this:
var query =
from u1 in table
join u2 in (
from u in table
group u by u.GroupId into g
select new { GroupId = g.Key, MaxStatus = g.Max(x => x.Status) }
) on new { u1.GroupId, u1.Status } equals new { u2.GroupId, Status = u2.MaxStatus}
select u1;
What about using Aggregate?
It's better than
Select max
Select by max value
since it only scans the array once.
var maxRow = table.Aggregate(
(a, b) => a.Status > b.Status ? a : b // whatever you need to compare
);
More one example:
Follow:
qryAux = (from q in qryAux where
q.OrdSeq == (from pp in Sessao.Query<NameTable>() where pp.FieldPk
== q.FieldPk select pp.OrdSeq).Max() select q);
Equals:
select t.* from nametable t where t.OrdSeq =
(select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)
Simply in one line:
var result = table.First(x => x.Status == table.Max(y => y.Status));
Notice that there are two action.
the inner action is for finding the max value,
the outer action is for get the desired object.