I have a picturelikes table in my database. For every like a new picture like table row will be created. I want to group those likes by lastweek and pictureid, meaning all the likes for one single pic in the last week should be accumulated and become one like.Then i will be able to sort them by thier count.
This is my picturelike table :
public partial class picturelike
{
public int idpicturelike { get; set; }
public int idpictures { get; set; }
public int iduser { get; set; }
public System.DateTime iddatetime { get; set; }
public int iduserlikedby { get; set; }
public int likenumber { get; set; }
}
Till now i am able to write this code, this is my web api controller code using linq.
var combo = from p in db.picturelikes
group p by new {p.iddatetime, p.idpictures } into pgroup
let count = pgroup.Count()
orderby count descending
select new SortedDto
{
IdPictures=pgroup.FirstOrDefault().idpictures,
IdPictureLike = pgroup.FirstOrDefault().idpicturelike,
IdUser = pgroup.FirstOrDefault().iduser,
IdDatetime = pgroup.FirstOrDefault().iddatetime,
IdUserLikedBy = pgroup.FirstOrDefault().iduserlikedby,
LikeNumber = pgroup.FirstOrDefault().likenumber
};
return combo;
So what else i need to do, how to make this code working, i am stuck here, how should i do it?
You cannot group by the last seven days. You have to filter first (where), then group:
var pastDate= DateTime.Now.Date.AddDays(-7);
var combo = from p in db.picturelikes
where p.iddatetime.Date > pastDate
group p by p.iddatetime.Date into pgroup
let count = pgroup.Count()
orderby count descending
select new SortedDto
{
IdPictures=pgroup.FirstOrDefault().idpictures,
IdPictureLike = pgroup.FirstOrDefault().idpicturelike,
IdUser = pgroup.FirstOrDefault().iduser,
IdDatetime = pgroup.FirstOrDefault().iddatetime,
IdUserLikedBy = pgroup.FirstOrDefault().iduserlikedby,
LikeNumber = pgroup.FirstOrDefault().likenumber
};
return combo;
An explaination of this line:
where p.iddatetime.Date > DateTime.Now.Date.AddDays(-7)
The Date property is just the date component of the time. We snap to midnight and filter by the logical days of the week, not by hours. This will give you more palatable results but feel free to change it.
To select only the rows from the last week, you can add a where clause to your linq statement, e.g.
where p.iddatetime > (DateTime.Today - TimeSpan.FromDays(7))
Related
We have an database with an this structure:
public partial class ChartData
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
public string Function { get; set; }
public int Duration { get; set; }
public bool IsError { get; set; }
}
Now we want to group the entries of this database by Timestamp.ToShortDateString() and then count the entries belonging to this date.
So for example we have:
2019-06-04 11:54:02,135,someFunction,30,False,
2019-06-04 11:55:03,135,someFunction,230,False,
2019-06-04 11:56:03,150,someFunction,4,True,
2019-06-05 11:54:03,230,someFunction,46,False,
2019-06-05 11:55:03,230,someFunction,46,False,
And I want this result:
{date: 2019-06-04, rows: 3}
{date: 2019-06-05, rows: 2}
public List <LogFileDTO> GetLogFilesData()
{
var items = db.ChartDatas.GroupBy(x = > new {
x.Timestamp.ToShortDateString
}).Select(x = > new LogFileDTO {
date = x.Timestamp.First(),
rows = x.Count ?
}).ToList();
}
So I do not really know how to group this input by date and then count the rows of each group.
You simply need to group on the Date property of the TimeStamp and then project using Select on the Key of each IGropuing and Count like below :
var items = db.ChartDatas.GroupBy(x => x.Timestamp.Date) // group only on Date
.Select(x => new LogFileDTO
{
Date = x.Key.ToShortDateString(),
Rows = x.Count()
}).ToList();
Key will contain only date part of DateTime object and Count() will tell the number of rows for that date in the group.
Hope it helps!
So i have a database that is connected with a device at the door that employees check when they come in and go out now i can get the history of statuses but i wanted to know how can I calculate the working hours for a day a week and a month for each employee. I got a this class for employee .
public class Employee : BaseEntity
{
public Employee()
{
this.HistoryOfStatuses = new List<Checkinout>();
this.TodayCheckedStatus = new List<Checkinout>();
}
public string Name { get; set; }
public string Department { get; set; }
public string CardNumber { get; set; }
public string Status { get; set; }
public byte[] Picture { get; set; }
public Checkinout ActualCheckinStatuse { get; set; }
public List<Checkinout> HistoryOfStatuses { get; set; }
public List<Checkinout> TodayCheckedStatus { get; set; }
public int UserId { get; internal set; }
And this is the checking status class
public class Checkinout : BaseEntity
{
public Checkinout()
{
}
public int EmployeeId { get; set; }
public string CheckStatus { get; set; }
public DateTime CheckTime { get; set; }
public Employee EmployeeObject { get; set; }
}
My controller looks something like this
public IActionResult Index()
{
using (var context = new RSAT.Api.Data.Proxy.ATT2018NOVUSContext())
{
var baseViewModel = base.GetLayoutViewModel();
var viewModel = new HomeViewModel()
{
User = baseViewModel.User,
RoleCollection = baseViewModel.RoleCollection,
TableCollection = baseViewModel.TableCollection,
//Olap = baseViewModel.Olap,
//Localization = baseViewModel.Localization,
EmployeeCollection = (from userinfo in context.Userinfo
join department in context.Dept on userinfo.Deptid equals department.Deptid
select new Employee()
{
Id = userinfo.Userid,
Name = userinfo.Name,
Picture = userinfo.Picture,
Department = department.DeptName,
CardNumber = userinfo.CardNum,
Status = userinfo.UserFlag.ToString(),
ActualCheckinStatuse = (from checkinout in context.Checkinout
join status in context.Status on checkinout.CheckType equals status.Statusid
where checkinout.Userid == userinfo.Userid
orderby checkinout.CheckTime descending
select new Checkinout
{
CheckStatus = status.StatusText,
CheckTime = checkinout.CheckTime
}).FirstOrDefault()
}).ToList()
};
return View(viewModel);
}
}
public IActionResult WorkingHours()
{
var inTime = "10:00";
var outTime = DateTime.Now.TimeOfDay;
var totalHours = Convert.ToDateTime(inTime).TimeOfDay.Subtract(outTime);
}
I wanted someones help to clear me out how to do this and how can i connect the last code in my controller .
Does your model have a property somewhere determining whether an entry is an in or out check? You will need this.
What you can do now is create a method that takes two dates that form a range. You can return the total work hours inside this range. You can then easily create a method for a week, month, year, where you specify the date ranges to this method.
Here's some pseudocode to get you started.
decimal GetRangeWorkHours(Employee employee, DateTime startOfRange, DateTime endOfRange){
//1. Ask the database for all the entries from this employee within the range of dates.
//2. Sort them by date, figuring out what entry the start/end is. You might get some edgecases where employees clock out midday and then clock back in later on the day. You can work this out using TimeSpans.
//3. Calculate the difference between all the now paired in/out entries.
//4. Sum the results of the previous step, return the result.
}
Consuming for week/month/year becomes easy
Employee someEmployee = new Employee(/*wetherever you use to identify employees*/);
//Replace these 2 values with whatever you need to provide your user with.
DateTime startOfRange = new DateTime(2019, 1, 1);
DateTime endOfRange = startOfRange.AddDays(7);
decimal workHours = GetRangeWorkHours(someEmployee, startOfRange, endOfRange);
Here is a sample table, in which I am going to extract the records with the highest priority, corresponding to each pair of ID and code, as below:
Here is my approach to hit the mark:
var max = from item in items
group item by new {item.code, item.id} into r
select new MyObjectType(r.Select(q => q.code),
r.Select(q => q.id),
r.Max(q => q.priority));
But the result is null...
Any idea to fix the problem?!
Edit:
Here is a brief example:
(code,id,priority)
(1,10,100)
(1,10,200)
(1,11,300)
(1,11,400)
(2,12,500)
(2,12,600)
(2,13,700)
(2,13,800)
And the result of the query should be:
(1,10,200)
(1,11,400)
(2,12,600)
(2,13,800)
Make public properties in class and do like this:
var max = from item in items
group item by new {item.code, item.id} into r
select new MyObjectType
{
Code = r.Key.code,
Id = r.Key.id,
MaxValue = r.Max(q => q.priority)
};
Your class should look like:
public class MyObjectType
{
public int Code { get; set; }
public int Id { get ; set; }
public int MaxValue { get; set; }
}
I am using EntityFramework 6 and running into some major speed issues -- this query is taking over two seconds to run. I have spent the better part of the day using LinqPad in order to speed up the query but I could only get it down from 4 to two seconds. I have tried grouping, joins, etc. but the generated SQL looks overly complicated to me. I am guessing that I am just taking the wrong approach to writing the LINQ.
Here is what I am attempting to do
Find all A where Valid is null and AccountId isn't the current user
Make sure the Collection of B does not contain any B where AccountId is the current user
Order the resulting A by the number of B in its collection in descending order
Any A that doesn't have any B should be at the end of the returned results.
I have to models which look like this:
public class A
{
public int Id { get; set; }
public bool? Valid { get; set; }
public string AccountId { get; set; }
public virtual ICollection<B> Collection { get; set; }
}
public class B
{
public int Id { get; set; }
public bool Valid { get; set; }
public string AccountId { get; set; }
public DateTime CreatedDate { get; set; }
public virtual A Property { get; set; }
}
The table for A has about one million rows and B will eventually have around ten million. Right now B is sitting at 50,000.
Here is what the query currently looks like. It gives me the expected results but I have to run an orderby multiple times and do other unnecessary steps:
var filterA = this.context.A.Where(gt => gt.Valid == null && !gt.AccountId.Contains(account.Id));
var joinedQuery = from b in this.context.B.Where(gv => !gv.AccountId.Contains(account.Id))
join a in filterA on gv.A equals a
where !a.Collection.Any(v => v.AccountId.Contains(account.Id))
let count = gt.Collection.Count()
orderby count descending
select new { A = gt, Count = count };
IQueryable<GifTag> output = joinedQuery
.Where(t => t.A != null)
.Select(t => t.A)
.Distinct()
.Take(20)
.OrderBy(t => t.Collection.Count);
Thanks
Well you could always try to remove these two lines from the joinQuery
where !a.Collection.Any(v => v.AccountId.Contains(account.Id))
and
orderby count descending
the first line have already been filtered in the first Query
and the orderline, well do do the ordering on the last Query so there is no point in doing it twice
I have this linq query in GridView
var table = from ll in dbo.Workers
join p in dbo.WorkDays on ll.Id equals p.Id
orderby p.Enter
select new
{
ll.Id,
ll.Name,
ll.Salary,
p.Enter,
p.ExitT,
p.Place,
WorkTime = Math.Round(getWorkTime(p.Enter, p.ExitT), 2),
Earned = Math.Round(getEarned(p.Enter, p.ExitT, ll.Salary), 2),
};
How can I add column of sum to the table?
Create class which will hold data and provide calculations based on that data:
public class WorkerInfo
{
// I don't know exact type of fields, but its enough for you to get the idea
public int Id { get; set; }
public string Name { get; set; }
public decimal Salary { get; set; }
public DateTime Enter { get; set; }
public DateTime ExitT { get; set; }
public string Place { get; set; }
public int WorkTime
{
get { return (ExitT - Enter).TotalDays; }
}
public decimal Earned
{
get { return WorkTime * Salary; }
}
}
Fill that these entities with data:
var workers = from ll in dbo.Workers
join p in dbo.WorkDays on ll.Id equals p.Id
orderby p.Enter
select new WorkerInfo
{
Id = ll.Id,
Name = ll.Name,
Salary = ll.Salary,
Enter = p.Enter,
ExitT = p.ExitT,
Place = p.Place
};
UPDATE Sample for returning aggregated data for all days:
var query = from w in dbo.Workers
join d in dbo.WorkDays on w.Id equals d.Id into days
let WorkTime = days.Sum(d => d.ExitT - d.Enter)
select new
{
w.Id,
w.Name,
w.Salary,
WorkTime,
Earned = WorkTime * w.Salary
};