Get distinct columns with order by date - c#

I have these following two tables:
Job Title | PostDate | CompanyId
Assitant | 12/15/10 | 10
Manager | 12/1/10 | 11
Developer | 12/31/10 | 10
Assitant | 12/1/10 | 13
PM | 11/29/10 | 12
CompanyId | Name
10 | Google
11 | Yahoo
12 | Microsoft
13 | Oracle
Now i would like to get 3 different companies with the jobs sorted by post date. The result table would be following:
Job Title | PostDate | CompanyName
Developer | 12/31/10 | Google
Manager | 12/1/10 | Yahoo
Assitant | 12/1/10 | Oracle
How can I achieve that using a linq query? Any help will be appreciated...

I think that would be something like:
var query = from company in db.Companies
join job in db.Jobs on company.CompanyId equals job.CompanyId
group job by company into jobsByCompany
let lastJob = jobsByCompany.OrderByDescending(x => x.PostDate)
.First()
orderby lastJob.PostDate descending
select new
{
JobTitle = lastJob.JobTitle,
PostDate = lastJob.PostDate,
CompanyName = jobsByCompany.Key.Name
};
It's a little odd to do a join and then a group - we could do a GroupJoin instead, but then discard empty options:
var query = from company in db.Companies
join job in db.Jobs on company.CompanyId equals job.CompanyId
into jobsByCompany // Make this a group join
let lastJob = jobsByCompany.OrderByDescending(x => x.PostDate)
.FirstOrDefault()
where lastJob != null
orderby lastJob.PostDate descending
select new
{
JobTitle = lastJob.JobTitle,
PostDate = lastJob.PostDate,
CompanyName = company.Name
};
EDIT: Note that doesn't just take the top three results. Use query = query.Take(3); to just get the first three results.

Related

Linq Left Outer Join With newest datetime in right side

I have "Orders" table where its primary key is "OrderId ":
OrderId | OrderName
------- | ----------
1 | Order X
2 | Order Y
3 | Order Z
and "OrderDetails" table where its primary key is "OrderDetailsId " foreign key is 'OrderId":
OrderDetailsId | OrderId | ItemId | DeliveryDate
-------------- | ------- | ------ | ------------
10 | 1 | AA | 1/1/2010
20 | 1 | BB | 1/1/2013
30 | 2 | CC | 1/1/2012
40 | 2 | CC | 1/1/2014
Each order has ZERO or more order details, each order detail has specific delivery date.
We want to get all the orders, whether they have order details or not, and mark just one order as VIP if it has the order detail that has the maximum "delivery date"
This is the expected output:
OrderId | OrderName | IsVIP
------- | --------- | -----
1 | Order X | NO
2 | Order Y | YES
3 | Order Z | NO (since it has no order details)
That's because the maximum delivery date is for OrderDetailsId = 40 which belongs to OrderId = 2
How to accomplish this using the most readable LINQ code
I am not sure if you have OrderDetails property in orders collection (if so then #juharr's answer is correct). But, if they are not then you can make use of group join like this:-
var result = from o in orders
join od in orderDetails
on o.OrderId equals od.OrderId into g
select new {
OrderId = o.OrderId,
OrderName = o.OrderName,
IsVIP = g.Any(x => x.DeliveryDate == orderDetails.Max(z => z.DeliveryDate))
? "Yes" : "No"
};
Here is an example Fiddle with linq-to-objects.
Use navigation properties. Note this will set IsVIP to "YES" for all orders that contain an order detail with the max delivery date.
var query = from order in db.Orders
select new
{
order.OrderId,
order.Name,
IsVIP = order.OrderDetails.Any(
od => od.DeliveryDate == db.OrderDetails.Max(x => x.DeliveryDate))
? "YES"
: "NO"
};

How I can filter a DataTable and create a new dataTable in ASP.NET with Linq?

hi i have a problem in my asp.net application.
I have a DataTable and I want to filter this table with linq to datatable.
my DataTable has this structure:
User | Licenses | Department | Time | Telephonenumber | Location
I want a new datatable with no dublicate entries in department. For example:
this are three rows in the basic dataTable
userA | 1 | IT | 4min | 0123/123 | germany
userB | 1 | Marketing | 3min | 0232/232 | germany
userC | 1 | IT | 1min | 0233/233 | germany
this I want:
Department | Licenses
It | 2
Marketing | 1
That means that the use licenes must be calculate.
Here is my Code:
UPDATE:
var query = from row in catia_user_table.AsEnumerable()
group row by row.Field<string>("Department") into grp
orderby grp.Key
select new
{
Department = grp.Key,
Licenses = grp.Sum(r => r.Field<int>("Licenses"))
};
DataTable tb = query.CopyToDataTable();
The think the Problem is that every row in my DataTable is from Typ string or is that not so importent?
Like #Krishnraj Rana said, you just need to group by Department, then use Sum operator to calculate total licenses for each Department. See below:
var query = catia_user_table.AsEnumerable().GroupBy(n => n.Department)
.Select(g => new
{
Department = g.Key,
Licenses = g.Sum(n => n.Licensec)
}).ToList();

Get first row of join

I have a linq query that joins two tables (no relation in the actual db)
the relation is:
Companies 1 - n Phones
var miniCompanies =
(from companies in db.Companies
join phones in db.Phones on companies.Id equals phones.CompanyId
select new
{
companies.Name,
phones.Phone,
}).ToList().Distinct();
this returns something like:
----------------------------
company1 | 12345 |
----------------------------
company1 | 23456 |
----------------------------
company2 | 43242 |
----------------------------
company2 | 34234 |
----------------------------
company2 | 65442 |
----------------------------
i need to get only the fisrt in Phones table not everything
how to do that?
Edit:maybe i wasn't clear about what want sorry for that.
i ment:
----------------------------
company1 | 12345 |
----------------------------
company2 | 43242 |
----------------------------
i want the first phone for each company
You can use GroupBy:
var miniCompanies =
(from companies in db.Companies
join phones in db.Phones on companies.Id equals phones.CompanyId
select new
{
companies.Name,
phones.Phone,
}).GroupBy(c=>c.Name).Select(c=>c.FirstOrDefault()).ToArray();
1 You can try with First operator
(from companies in db.Companies
join phones in db.Phones on companies.Id equals phones.CompanyId
select new
{
phones.Phone,
}).First();
Link : http://msdn.microsoft.com/fr-fr/library/vstudio/system.linq.queryable.first.aspx
2 You can also use FirstOrDefault
Link : http://msdn.microsoft.com/fr-fr/library/vstudio/system.linq.queryable.firstordefault.aspx
3 You can also use Take(1);
Link : http://msdn.microsoft.com/fr-fr/library/vstudio/bb300906.aspx
I would use the following:
var miniCompanies =
(from companies in db.Companies
join phones in db.Phones on companies.Id equals phones.CompanyId
select new
{
companies.Name,
phones.Phone,
}).ToList().Distinct().FirstOrDefault();
The 'FirstOrDefault()' method will return the first item in the collection. If the collection contains no elements, the default object will be returned. For nullable types, this will be a 'null' object. This is a good way to prevent your application from failing due to an exception related to an empty collection.

LINQ join and group

I'm new to LINQ, and I'm trying to convert this SQL query into its LINQ equivalent:
select S.*
from Singles S
join (
select max(SingleId) as SingleId
from Single
group by ArtistId) S2 on S2.SingleId = S.SingleId
order by Released desc
The table looks like this:
-----------
| Singles |
|-----------|
| SingleID |
| ArtistId |
| Released |
| Title |
| ..... |
-----------
and so on...
And contains for example these items:
SingleID ArtistID Released Title
1 1 2011-05-10 Title1
2 1 2011-05-10 Title2
3 2 2011-05-10 Title3
4 3 2011-05-10 Title4
5 4 2011-05-10 Title5
6 2 2011-05-10 Title6
7 3 2011-05-10 Title7
8 5 2011-05-10 Title8
9 6 2011-05-10 Title9
So I'm trying to get the latest singles, but only one per artist. Could anyone help me? :)
Maybe there's even a better way to write the query?
Update:
To answer the questions posted in the comments:
We're using Microsoft SQL Server, and LINQ to NHibernate.
Here's a sample that we're using right now, that returns the latest singles, without grouping by artistid:
public Single[] GetLatest()
{
IQueryable<Single> q;
q = from s in _sess.Query<Single>()
where s.State == State.Released
orderby s.Released descending
select s;
return q.Take(20).ToArray();
}
How about this:
var firstSingles = Singles.GroupBy(x => x.ArtistId)
.Select(g => g.OrderByDescending(x => x.Released).First())
.ToList();
Something like this should work.
var query = from s in db.Singles
group s by s.ArtistID into sg
let firstSingle = sg.OrderByDescending(r => r.SingleID).FirstOrDefault()
select new
{
ArtistID = sg.Key,
SingleID = firstSingle.SingleID,
Released = firstSingle.Released,
Title = firstSingle.Title,
}
singles
.OrderByDescending(s => s.SingleID)
.GroupBy(s => s.SingerID, (id, s) => new
{
SingleID = id,
Title = s.First().Title
});

Linq - Group by multiple tables

Using Linq to Sql how do i group the following 2 tables.
Orders Table:
CustomerID | Name |Date
1 | order1 | 2010-01-01
2 | order2 | 2010-01-01
2 | order3 | 2010-04-01
Calls Table:
CustomerID | Name |Date
1 | call1 | 2010-01-01
3 | call2 | 2010-06-01
2 | call3 | 2010-05-01
I want to group the two tables by date , Result:
Date | Orders | Calls
2010-01-01 | 2 | 1
2010-04-01 | 1 | 0
2010-05-01 | 0 | 1
2010-06-01 | 0 | 1
i know how to group a single table ,
from o in Orders
group o by o.Date.Date into og
select new {Date = og.Key,Orders= og.Count()};
how do i group both?
thx!
Since both tables seem to have a similar structure I'd recommend projecting both into an equivalent form and then group on the concatenation of those two sets.
var orders = from o in Orders
select new { IsOrder = true, o.Date };
var calls = from c in Calls
select new { IsOrder = false, c.Date };
var result = from x in orders.Concat(calls)
group x by x.Date into og
select new {Date = og.Key, Orders= og.Count(o=>o.IsOrder), Calls = og.Count(c=>!c.IsTrue)};
Due to the lazy nature of Linq2Sql this might actually be reduced to a single query. In the interest of performance I would make sure this is not a query from hell.
You can use the Union method:
var result =
(from c in Calls group c by c.Date into cg select new {Date = cg.Key, Calls = cg.Count(), Orders = 0})
.Union(from o in Orders group o by o.Date into og select new {Date = og.Key, Calls = 0, Orders = og.Count()})
.GroupBy(x => x.Date)
.Select(g => new {Date = g.Key, Calls = g.Max(r => r.Calls), Orders = g.Max(r => r.Orders)});
foreach (var row in result)
{
Trace.WriteLine(row);
}
This is very similar to the SQL you would write (a union of the two tables, and then an outer query to merge the results into a row)

Categories