I have a datatable whose columns are name, code, dateAndTime. Now I want to get the count of all the records for every hour in a Day using LINQ.
DateTime Column contains data as
2014-08-01 07:00:06.163
2014-08-01 07:00:11.873
2014-08-01 07:00:42.623
2014-08-01 07:00:48.363
2014-08-01 07:01:15.243
2014-08-01 07:01:16.507
Now I want to get the count of all the records from the start of the day to the end of the day hourly basis.
Example would be :
7 O Clock : 56 Records
8 O Clock : 90 Records
..
..
etc.
How it can be possible via LINQ ?
If your column type is DateTime then you can group by its Hour property and get count for each hour like:
var query = dt.AsEnumerable()
.GroupBy(row => row.Field<DateTime>("dateAndTime").Hour)
.Select(grp => new
{
Hour = grp.Key,
Count = grp.Count()
});
where dt is your DataTable
EDIT: The above should work as long as you have data for a single date in your DataTable, but if you have rows for multiple dates then grouping should be done on Date as well as Hour like:
var query = dt.AsEnumerable()
.GroupBy(row => new
{
Date = row.Field<DateTime>("dateAndTime").Date,
Hour = row.Field<DateTime>("dateAndTime").Hour
})
.Select(grp => new
{
Date = grp.Key.Date,
Hour = grp.Key.Hour,
Count = grp.Count()
});
I assume that the column really stores DateTimes, you can group by Date + Hour:
var hourGroups = dataTable.AsEnumerable()
.Select(row => new { DateAndTime = row.Field<DateTime>("dateAndTime"), Row = row })
.GroupBy(x => new { Date = x.DateAndTime.Date, Hour = x.DateAndTime.Date.Hour });
foreach (var x in hourGroups)
Console.WriteLine("Date: {0} Hour: {1}: Count: {2} All names: {3}",
x.Key.Date.ToShortDateString(),
x.Key.Hour,
x.Count(),
string.Join(",", x.Select(xx => xx.Row.Field<string>("name")))); // just bonus
Related
Hi I have a list like below
var data2 = dt.AsEnumerable().Select(x => new
{
SubTask = x.Field<string>("subtask"),
Name = x.Field<string>("FirstName"),
Date = x.Field<string>("Day") + ", " + x.Field<string>("Date"),
Hour = System.Text.Encoding.UTF8.GetString(x.Field<System.Byte[]>("EmpHours"))
});
My list is like below
Name Date Hour Subtask
---- ------ ------- ----------
a 2018-11-01 1 task1
a 2018-11-01 2 task2
b 2018-11-01 'PTO' 'PTO'
c 2018-11-01 5 design
c 2018-11-01 3 coding
I want to group by date and name and display the result in a innerlist inside the main list.
I wanted to group by date and name and then sum the hour column for each name.
The hour column is string type 'It may contain string 'PTO' or number like '2'.
I tried below query
var data2 = dt.AsEnumerable().Select(x => new
{
SubTask = x.Field<string>("subtask"),
Name = x.Field<string>("FirstName"),
Date = x.Field<string>("Day") + ", " + x.Field<string>("Date"),
Hour = System.Text.Encoding.UTF8.GetString(x.Field<System.Byte[]>("EmpHours")),
EmpList= (from grp in dt.AsEnumerable()
.GroupBy(row => new {
Name = row.Field<string>("Name"),
Date = row.Field<string>("Date")
}).Select(g => new { Date = g.Key.Date, Name = g.Key.Name, Hour = g.Sum(i => i.Field<decimal>("Hour"));
})
I want output like below table
Name Date Hour Subtask
---- ------ ------- ----------
a 2018-11-01 3 task1.task2
b 2018-11-01 'PTO' 'PTO'
c 2018-11-01 8 design,coding
can anyone help me on this?
Basically what you're trying to do will require you to know if Hour is numeric and also group on that. The below would seem to do what you're after
var result = data.GroupBy(x => new {
x.Name, // Group on Name
x.Date, // And date
IsHourNumeric=x.Hour.All(Char.IsNumber) // And whether Hour is numeric
})
.Select(g => new {
Name = g.Key.Name,
Date = g.Key.Date,
Hour = g.Key.IsHourNumeric
? g.Select(x => int.Parse(x.Hour)).Sum().ToString() // If hour was numeric sum
: g.First().Hour, // Otherwise just take the first item ?!?
SubTasks = g.Select(x => x.SubTask)
});
A live example with your data is here: https://rextester.com/DPJZUH68065
apply linq group by after your initial results (added .TOList())
var data2 = dt.AsEnumerable().Select(x => new
{
SubTask = x.Field<string>("subtask"),
Name = x.Field<string>("FirstName"),
Date = x.Field<string>("Day") + ", " + x.Field<string>("Date"),
Hour = System.Text.Encoding.UTF8.GetString(x.Field<System.Byte[]>("EmpHours"))
}).ToList();
Now apply group by to this result like below example:
var result = data2.GroupBy(n => new { n.Name, n.Date})
.Select(cl => new Result
{
Name = cl.First().Name,
Date = cl.First().Date,
Hours = cl.Sum(c => c.Hour),
}).ToList();
I have a customers table and I want to return count of rows inserted each month or Customers registered each month. The following code returns only month and record count but I want to record 0 if say for Jan no customers where registered. Thank you.
The following code returns:
Month 2 Count 15
Month 5 Count 11
Month 9 Count 82
I also want to return
Month 1 count 0
Month 3 count 0
so on..
My code:
var query = (from customers in context.customers
group customers by customers.RegisterDateTime.Month into g
select new
{ Month = g.Key, Count = g.Count() }
).ToList();
foreach (var data in query)
{
Console.WriteLine( "Month "+ data.Month +" Count "+ data.Count);
}
var query = (from m in Enumerable.Range(1, 12)
join c in context.customers on m equals c.RegisteredDateTime.Month into monthGroup
select new { Month = m, Count = monthGroup.Count() }
).ToList();
I assume that you want the range from the lowest month and the highest month.
I see no possiblity (but maybe there is?) to do it inside your query directly. I would add the "0" after the query to fill the gaps between the range with zeros.
So I would add the following code line after your query:
var lowestKey = result.Min(x => x.Month);
var highestKey = result.Max(x => x.Month);
query = query.Union(
Enumerable.Range(lowestKey, highestKey - lowestKey)
.Where(e => !result.Any(r => r.Month == e))
.Select(s => new { Month = s, Count = 0 })
).OrderBy(o => o.Month).ToList();
Since I don't have your complete code, this query maybe need some adjustment.
If you need another range, than you can simple change it.
My complete example look like this:
static void Main(string[] args)
{
// Initialize the list
var result = new []
{
new { Month = 2, Count = 15 },
new { Month = 5, Count = 11 },
new { Month = 9, Count = 82 }
}.ToList();
// Generate a List with 0 in Range
var lowestKey = result.Min(x => x.Month);
var highestKey = result.Max(x => x.Month);
result = result.Union(
Enumerable.Range(lowestKey, highestKey - lowestKey)
.Where(e => !result.Any(r => r.Month == e))
.Select(s => new { Month = s, Count = 0 })
).OrderBy(o => o.Month).ToList();
foreach (var data in result)
{
Console.WriteLine("Month " + data.Month + " Count " + data.Count);
}
Console.ReadKey();
}
Hope it helps,
var query = (from customers in context.customers
group customers by customers.RegisterDateTime.Month into g
select new
{ Month = g.Key, Count = g.Count(x=>x!=null) }
).ToList();
I have a collection of flyers with a property FlyerDate as datetime and I want to create a dropdown list with month and year, such "nov 2015, dec 2015, jan 2016"...
This is my code:
var monthList = flyers.Where(i => i.FlyerDate != DateTime.MinValue && i.FlyerDate.Year >= 2013)
.GroupBy(i => i.FlyerDate.Month)
.Select(g => new {
Month = g.Key,
Year = g.First(i => i.FlyerDate != DateTime.MinValue).FlyerDate.Year,
FullDate = String.Concat(DateTimeFormatInfo.CurrentInfo.GetMonthName(g.Key), " ", g.First(i => i.FlyerDate != DateTime.MinValue).FlyerDate.Year),
Total = g.Count(i => i.FlyerID > 0)
}
);
I would that the GroupBy works both on month and year as in my case the list contains only the first occurrence of each months. Any hints?
You need to group by an anonymous type containing both, the year and the month:
var monthList = flyers.Where(i => i.FlyerDate.Year >= 2013)
.GroupBy(i => new { i.FlyerDate.Year, i.FlyerDate.Month })
.Select(g => new {
Year = g.Key.Year,
Month = g.Key.Month,
FullDate = DateTimeFormatInfo.CurrentInfo.GetMonthName(g.Key.Month) + " " + g.Key.Year
});
Btw, if you want the abbreviated month-name as your desired result suggests you need to use DateTimeFormatInfo.CurrentInfo.GetAbbreviatedMonthName instead of GetMonthName.
I suspect your issue may be the GroupBy(i => i.FlyerDate.Month) clause. That grouping doesn't appear to respect year, so you'd be left with only 12 groups by the time you make it to your Select.
Incorporating the year into that GroupBy lambda could create a unique group for each month. Assuming your Month and Year are ints:
.GroupBy(i => (i.FlyerDate.Year * 12) + i.FlyerDate.Month)
might be a good place to start.
var query = flyers.GroupBy(f => f.FlyerDate.ToString("MMM yyyy"))
foreach (var group in query)
{
Console.WriteLine(group.Key);
foreach (Flyer f in group)
Console.WriteLine(f.FlyerDate);
}
i have a sql query, but what would be the equivalent for this in c# LINQ ?
SELECT CAST(DateAdded as date) AS ForDate,
DATEPART(hour,DateAdded) AS OnHour,
COUNT(*) AS Totals
FROM [TABLE1].[dbo].[PartValues]
GROUP BY CAST(DateAdded as date),
DATEPART(hour,DateAdded)
Order by ForDate Desc,
OnHour Desc
The idea is to count records by date and hour- like this :
ForDate OnHour Totals
2016-05-25 9 36
2016-05-25 8 60
2016-05-25 7 70
2016-05-25 6 12
2016-05-24 21 24
2016-05-24 20 72
2016-05-24 19 24
2016-05-24 14 120
You can use DbFunctions.TruncateTime to extract the date part of the DateAdded column. This code should work:
var result = context.PartValues
.GroupBy(x => new
{
Date = DbFunctions.TruncateTime(x.DateAdded), //Extract Date only (time part is 0)
Hour = x.DateAdded.Hour
}).Select(g => new
{
g.Key.Date,
g.Key.Hour,
Total = g.Count()
})
.ToList();
See the code below:
var results = context.partValues.GroupBy(r =>
new DateTime(r.dateAdded.Year,
r.dateAdded.Month,
r.dateAdded.Day,
r.dateAdded.Hour, 0, 0),
(d, r) => new { date = d, totals = r.Count() });
I have a list of dates. I would like to query the list and return a list of pairs where the first item is a date and the second is the date which occurs just before the first date (in the list).
I know this could easily be achieved by sorting the list and getting the respective dates by index, I am curious how this could be achieved in LINQ.
I've done this in SQL with the following query:
SELECT Date,
(SELECT MAX(Date)
FROM Table AS t2
WHERE t2.Date < t1.Date) AS PrevDate
FROM Table AS t1
It is easy as converting your current query into a LINQ query:
var result = table.Select(x =>
new
{
Date = x.Date,
PrevDate = table.Where(y => y.Date < x.Date)
.Select(y => y.Date)
.Max()
});
List<DateTime> dates = new List<DateTime>()
{
DateTime.Now.AddDays(1),
DateTime.Now.AddDays(7),
DateTime.Now.AddDays(3),
DateTime.Now.AddDays(6),
DateTime.Now.AddDays(5),
DateTime.Now.AddDays(2),
DateTime.Now.AddDays(3),
};
dates = dates.OrderByDescending(x => x).ToList();
var result = dates.Skip(1)
.Select((x, i) => new { Date = dates[i], PreviousDate = x });