SUM and DISTINCT of two different columns - sql-server

I have a table Employee with say the following records
EmpID Salary Date
10 2000 1/1/2011
10 2000 2/1/2011
20 2000 1/1/2011
I want to count the total number of employees and the total salary (based on some other parameters)
Is there a easy way to write the following SQL query in entity framework.
select Sum(Salary), count(distinct(EmployeeID)) from empdb.employeesalary (where clause)
Have a class into which I need to select these values
class EmployeeEntity
{
decimal TotalAmount;
int EmployeeCount
}
I currently do two queries in EF as follows
objectcontext.employeesalary.Sum(c => c.Salary);
objectcontext.employeesalary.Select(c => c.EmployeeID).Distinct().Count();
How can I merge these into a single statement using Entity Framework. Am I missing something here.

Try something like this:
objectcontext.employeesalary
.Where(c => ...)
.GroupBy(_ => default(string))
.Select(g => new
{
Sum = g.Sum(c => c.Salary),
Count = g.Select(c => c.EmployeeID).Distinct().Count()
});

how about this ? you can merge your result of EF into your Employee Entity Class
var q = from f in objectcontext.employeesalary
where [clause]
group f by f.EmpID into g
select new EmployeeEntity
{
TotalAmount = g.Sum(c => c.Salary),
EmpmloyeeCount = g.Select(c => c.EmployeeID).Discinct().Count()
}
var EmployeeSummary = new List<EmployeeEntity>(q.ToList());

Related

asp.net mvc5 , raw sql : Display data in Views generated using aggregate function

I am using ASP.NET MVC, EF and SQL Server 2014.
I want to generate a view which would show total sick leave and annual leave an employee with employee id. I found a LINQ query very complicated and I don't know how to use it in Asp.net MVC. I wrote a controller for this purpose and now I have no idea how to display this data in the view.
Please help me with this. If there is better way of doing this or if I am making mistakes, please let me know.
SQL queries are below:
SELECT
[EmployeeId], SUM(AssignedLeaveDay) AS Total_Annual_Leave
FROM
AssignLeaves
WHERE
[EmployeeId] = 1 AND LeaveTypeId = 4
GROUP BY
[EmployeeId]
SELECT
[EmployeeId], SUM(AssignedLeaveDay) AS Total_Sick_Leave
FROM
AssignLeaves
WHERE
[EmployeeId] = 1 AND LeaveTypeId = 5
GROUP BY
[EmployeeId]
enter image description here
//Controller side
var Data = from data in AssignLeaves.Where(s => s.EmployeeId == 1 && s.LeaveTypeId == 4)
group data by data.EmployeeId into g
select new
{
EmployeeId = g.Key,
Total_Annual_Leave = g.Sum(x => x.AssignedLeaveDay)
};
var SickLeaveData = from data in AssignLeaves.Where(s => s.EmployeeId == 1 && s.LeaveTypeId == 5)
group data by data.EmployeeId into g
select new
{
EmployeeId = g.Key,
Total_Sick_Leave = g.Sum(x =>
x.AssignedLeaveDay)
};
You get Total Annual leave by: Data.FirstOrDefault().Total_Annual_Leave ;
You get Total_Sick_Leave by: SickLeaveData.FirstOrDefault().Total_Sick_Leave;

Select specific columns with repository in Entity Framework Core

I have a big table with a binary column for picture. I need to show contents of this table in a view and make it searchable. I have tried only selecting a subset of columns that are needed in this. However, the generated SQL always has all the columns of the table in the generated query.
public IQueryable<ApplicantDTO> GetApplicantQueryable()
{
return DataContext.Applicants
.Include(a => a.Nationality)
.Select(x => new ApplicantDTO
{
Id = x.Id,
BirthDate = x.BirthDate,
Gender = x.Gender,
FirstName = x.FirstName,
LastName = x.LastName,
OtherName = x.OtherName,
MobileNo = x.MobileNo,
Age = x.Age,
Nationality = x.Nationality.National,
Admitted = x.admitted,
Completed = x.Completed
})
.Where(a => a.Admitted == false && a.Completed == true)
.OrderBy(a => a.LastName)
.AsNoTracking();
}
But instead of just specifying the above rows, the generated SQL from profiler is
SELECT
[a].[Id], [a].[BirthDate], [a].[BirthPlace], [a].[CompleteDate],
[a].[Completed], [a].[ContentType], [a].[CreateDate],
[a].[Denomination], [a].[Disability], [a].[Email],
[a].[FirstName], [a].[Gender], [a].[HomeTown], [a].[LastName],
[a].[MarryStatus], [a].[MatureApp], [a].[MobileNo], [a].[NationalityID],
[a].[OtherName], [a].[Passport], [a].[Pin], [a].[PostalAddress],
[a].[Region], [a].[Religion], [a].[ResAddress], [a].[SerialNo],
[a].[Title], [a].[VoucherID], [a].[admitted], [a.Nationality].[National]
FROM
[Applicants] AS [a]
INNER JOIN
[Nationality] AS [a.Nationality] ON [a].[NationalityID] = [a.Nationality].[Id]
WHERE
([a].[admitted] = 0)
AND ([a].[Completed] = 1)
ORDER BY
[a].[LastName]
With all the underlying columns all included in the query.
I tried putting it in an anonymous type before casting it to the ApplicantDTO but still the same effect.
What's wrong?

How to convert SQL Query into LinQ

I'm new to SQL, please Help me how to convert this query into LinQ
This is My Table Dept:
Id Name Sal Department
1 John 40000 Dotnet
2 mick 45000 DotNet
3 Pillay 777 Sql
Here I want to display Salary Based On Department Name, like:
DepartmentName ToalSal
Dotnet 85000
Sql 777
select DeprtmentName,sum(sal) from Dept_Emp Group by DeprtmentName
I wrote some Part of query
public IEnumerable<Dept_Emp> GetJam()
{
var x = from n in db.Dept_Emp
group n by n.Sal into g
select new
{
DeprtmentName = g.Key
};
// what I mention Here;
}
You are missing calculating sum of sal fields of grouped entities. Also you are grouping by wrong field. You should use department name for grouping
from de in db.Dept_Emp
group de by de.DeprtmentName into g
select new {
DepartmentName = g.Key,
TotalSalary = g.Sum(x => x.Sal) // aggregation here
}
What you have as output is anonymous objects. You cannot return them directly from method. You have several options here
Create custom class like DepartmentTotals with name and total salary fields, and return instances of this class instead of anonymous objects. Then return type will be IEnumerable<DepartmentTotals>.
Create Tuple<string, int> (or whatever type of salary). And return such tuples.
Use C# 7 tuples.

Linq Query Condition for multiple row

I tried to solve one query from last 2 days but didn't.
It looks easy to understand but can't made.
There are two column in Table for example:
ResourceId || MappingId
1 2
1 3
2 2
2 4
3 2
3 4
4 2
4 5
5 2
5 4
This is one table which have two fields ResourceId and MappingId.
Now I want resourceId which have Mappingid {2,4}
Means answer must be ResourceId {2,3,5}
How can I get this answer in Linq Query?
Use Contains of collection. This method can be translated by Entity Framework into SQL IN operator:
int[] mappingIds = { 2, 4 };
var resources = from t in table
where mappingIds.Contains(t.MappingId)
select t.ResourceId;
Lambda syntax:
var resources = table.Where(t => mappingIds.Contains(t.MappingId))
.Select(t => t.ResourceId);
Generated SQL will look like:
SELECT [Extent1].[ResourceId]
FROM [dbo].[TableName] AS [Extent1]
WHERE [Extent1].[MappingId] IN (2,4)
UPDATE: If you want to get resources which have ALL provided mapping ids, then
var resources = from t in table
group t by t.ResourceId into g
where mappingIds.All(id => g.Any(t => t.Id == id))
select g.Key;
Entity Framework is able to translate this query into SQL, but it will not be that beautiful as query above.
IQueryable<int> resourceIds = table
// groups items by ResourceId
.GroupBy(item => item.ResourceId)
// consider only group where: an item has 2 as MappingId value
.Where(group => group.Select(item => item.MappingId).Contains(2))
// AND where: an item has 4 as MappingId value
.Where(group => group.Select(item => item.MappingId).Contains(4))
// select Key (= ResourceId) of filtered groups
.Select(group => group.Key);

SqlCeException-Expressions in the ORDER BY list cannot contain aggregate functions

I have the following code which counts vehicles grouped by vehicle type.
using (var uow = new UnitOfWork(new NHibernateHelper().SessionFactory)) {
var repo = new Repository<Vehicle>(uow.Session);
var vtSummary= repo.ListAll()
.GroupBy(v => v.VehicleType.Name)
.Select(v => new NameCount {
EntityDescription = v.First().VehicleType.Name,
QtyCount = v.Count() })
.OrderByDescending(v => v.QtyCount).ToList();
uow.Commit();
return vtSummary;
}
The above produces the following sql code:
SELECT VehicleType.Name as col_0_0_,
CAST(COUNT(*) AS INT) as col_1_0_
FROM Vehicle vehicle0_
LEFT OUTER JOIN VehicleType vehicletype1_
ON vehicle0_.VehicleTypeId= VehicleType.Id
GROUP BY VehicleType.Name
ORDER BY CAST(COUNT(*) AS INT) DESC
The SQL code runs perfectly well under MS SQL Server but testing under SQl CE it produces the following error:
System.Data.SqlServerCe.SqlCeException : Expressions in the ORDER BY list cannot contain aggregate functions.
A solution from Sub query in Sql server CE is to specify an alias for the column and use the alias in the order by clause.
Is there any way to provide an alias in the LINQ expression that I am using to enable it run without raising errors?
You can perform the OrderBy in memory, with LINQ to objects:
var vtSummary= repo.ListAll()
.GroupBy(v => v.VehicleType.Name)
.Select(v => new NameCount {
EntityDescription = v.First().VehicleType.Name,
QtyCount = v.Count() })
.AsEnumerable() //SQL executes at this point
.OrderByDescending(v => v.QtyCount).ToList();

Resources