Quick linq count question - c#

I have the following query that returns the login count per day from a given date.
var sot = from uts in DataContext.UserTrackingStatistics
let startDate = new DateTime(2009, 10, 01)
where uts.LastLogin >= startDate
group uts by uts.LastLogin.Date into myGroup
orderby myGroup.Key.Date
select new { Count = myGroup.Count() , myGroup.Key.Date};
I would like this to say the count was 0 for a given day rather than not return anything. How could I do that within this query?

You can't do it just with LINQ-to-SQL, as you'd have to use a union on your query with data that doesn't actually exist, which LINQ-to-SQL can't do.
To do this, you'll need to fill in the gaps client-side. I'm not in front of VS at the moment, but a general approach would be this:
Define your date range (since you mention no end date in your code and we're talking about login date, I'm assuming that the end date would be the current date.
Use Enumerable.Range to create a list of numbers ranging from 0 to the number of days within your date range, then use Select to transform that list into a list of dates. Select your results using an anonymous type and use the same properties as your L2S statement; this way, the compiler will reuse the same type
Combine your lists together using an outer join (not the most obvious syntax in LINQ, unfortunately) on the Date property
Order your results by date
This will now show 0 for the gaps.
I'll try to post a code sample below, but note that I can't compile where I am, so it may require tweaking.
var allDates = Enumerable.Range(0, (DateTime.Today - startDate).TotalDays)
.Select(i => new { Count = 0, Date = startDate.AddDays(i) });
var fullResults = from d in allDates
join r in results on d.Date == r.Date
from oj in r.DefaultIfEmpty()
select new { Count = oj == null ? 0 : oj.Count, Date = d.Date };

Related

linq - dynamic group by different functions of date

below my simple sql query
SELECT source, date ,COUNT (*)
FROM query
WHERE source in ('a value')
GROUP BY source, date
it took me a while to understand and implement it in linq notation (also thanks to hints from this site) by finally I did it
var selekt = dt.AsEnumerable();
var alldata = from ad in selekt
where ad["source"].ToString().Equals(this.comboBox1.Text)
group ad by new
{
err = ad["err"],
date = ad["date"]
}into g
orderby g.Key.err ascending, g.Key.channel descending
select new
{
Name = g.Key.err,
Date = g.Key.date,
C = g.Count()
};
It is more or less what I need, it also contains "dynamic" element in where clause.
The last point I can't get it is dynamic group clause.
Depends on values on the form I want to group this query by one of three functions of date: day/week/month. I suppose the most difficult part could be group by week.
Anyway, every hint regarding this topis are welcome

LINQ query issue regarding Date

I want to list out all records where CloseDate is greater than DateTime.Now.
I have write a query for that but it doesn't fetch records where CloseDate is greater than DateTime.Now.
See my query below
var query = (from x in objEntity.VacancyMsts
join o in objEntity.OrganizationMst on
x.OrganizationID equals o.OrganizationId into vacorg
from o in vacorg.DefaultIfEmpty()
where x.Status == true && x.CloseDate >= DateTime.Now
select new VacancyMstDTO
{});
Is there any problem in my query?
you dont need to join here if you have a FK relationship
var query = from x in objEntity.VacancyMsts
where x.Status && x.CloseDate >= DateTime.Now
select new VacancyMstDTO
{
OrganizationName = x.OrganizationMst.Name,
...
};
But I wonder if you really want the CloseDate to be ahead of today, normally a close date happens in the past, no?
And, careful with timezones as well. I tend to always insert/update the database with DateTime.UtcNow and when reading, apply the user timezone...

Comparing two dates in LINQ to SQL

I have a database with a table named meeting. Meeting dates are stored in this table using the following format: May 2nd 2011 is (for example) formatted as 5/2/2011.
My requirement is to get the meetings between two dates (say, 4/25/2011 and 5/2/2011) and to write a query comparing a date with these two dates. Does it compare like 4/25/2011 < 4/26/2011? How does the comparison take place?
I am using SQL Server 2008 and LINQ to SQL queries.
Something like this
DateTime start = new DateTime("4/25/2011");
DateTime end = new DateTime("5/2/2011");
var result = db.Meeting.Where(d => d.MeetingDate >= start
&& d.MeetingDate <= end);
Query style:
from m in db.Meetings
where m.Start => start && m.End <= end
select m;
Method style:
db.Meetings.Where(m => m.Start => start && m.End <= end);

LINQ querying for multiple dates and counting rows

Hi I want to know how to do two things with LINQ
This question is probably more a SQL/C# thing I firstly want to query with multiple dates
How would I do this?
For example I want to query every date in 2011 in a DateTime SQL Column So I want to find 01/01/2011 to 31/12/2011 I guess I would replace the first day month numbers with something e.g ##/##/2011
Secondly how do I count rows would it be like this "var rowCount = qRows.Count();"
Thanks
try this :
List<Order> ord = (from o in dc.Orders
where o.OrderDate.Value.Year == 2011
select o).ToList();
int Count = ord.Count;
from x in somethingwithdate
where x.adate > '1/1/2000'
where x.adate < '1/1/2010'
select x
you can also do x.Count
You can do myDate.AddDays(1) repeated as many times as necessary.
Yes, you can do a Count() on the returned LINQ dataset.
Slightly different take on earlier answer(if you were pulling the date from another object for instance):
DateTime myDate = new DateTime(2011,1,1);
var results = (from t in dc.events
where t.event_date.Value.Year.Equals(myDate.Year)
select t).ToList();
int testCount = results.Count();

Grouping by Time ranges in Linq

I've been getting stuck into some linq queries for the first time today and I'm struggling with some of the more complicated ones. I'm building a query to extract data from a table to build a graph. The tables colums I'm interested in are Id, Time and Value.
The user will select a start time, an end time and the number of intervals (points) to graph. The value column will averaged for each interval.
I can do this with a linq request for each interval but I'm trying to write it in one query so I only need to go to the database once.
So far I have got:
var timeSpan = endTime.Subtract(startTime);
var intervalInSeconds = timeSpan.TotalSeconds / intervals;
var wattList = (from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
group t by intervalInSeconds // This is the bit I'm struggling with
into g
orderby g.Key
select g.Average(a => a.Value))
).ToList();
Any help on grouping over time ranges will be most welcome.
I've done this myself for exactly the same situation you describe.
For speed, modified the database's datapoints table to include an integer-based time column, SecondsSince2000, and then worked with that value in my LINQ to SQL query. SecondsSince2000 is a computed column defined as:
datediff(second, dateadd(month,1200,0), DataPointTimeColumn) PERSISTED
Where DataPointTimeColumn is the name of the column that stores the datapoint's time. The magic function call dateadd(month,1200,0) returns 2000-01-01 at midnight, so the column stores the number of seconds since that time.
The LINQ to SQL query is then made much simpler, and faster:
int timeSlotInSeconds = 60;
var wattList =
(from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
group t by t.SecondsSince2000 - (t.SecondsSince2000 % timeSlotInSeconds)
into g
orderby g.Key
select g.Average(a => a.Value))).ToList();
If you can't modify your database, you can still do this:
var baseTime = new DateTime(2000, 1, 1);
var wattList =
(from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
let secondsSince2000 = (int)(t.Time- baseTime).TotalSeconds
group t by secondsSince2000 - (secondsSince2000 % timeSlotInSeconds)
into g
orderby g.Key
select g.Average(a => a.Value))).ToList();
The query will be quite a bit slower.
Check out this example I wrote a while ago. It sounds like what you are trying to do, but I'm not sure if it does the grouping in SQL or by .NET.
http://mikeinmadison.wordpress.com/2008/03/12/datetimeround/
Maybe you can do something like:
var wattList = (from t in _table
where t.Id == id
&& t.Time >= startTime
&& t.Time <= endTime
).GroupBy(x => (int) ((x.Time - startTime).TotalSeconds / intervalInSeconds))
.Select(grp => grp.Average(x => x.Value));

Categories