how to groupby items List<keyvaluepair <string,datetime[]>> over date - c#

I have a datatable filled by date , day ,name and type so I read from this datatable into List> using C#.net so
the code is this :
dicArray = dtrd.AsEnumerable()
.Select(Row => Row["IDp"]).Distinct()
.Select(Id => new KeyValuePair<string, string[]>(
Id.ToString(),
dtrd.AsEnumerable()
.Where(Row => Row["IDp"].ToString() == Id.ToString())
.Select(Row => Row["date"].ToString()+";"+ Row["day"].ToString()+";"+Row["nobatkari"].ToString() + ";" + Row["pname"].ToString())
.ToArray()))
.ToList();
now I want to count each item over date I mean that I want to know how many rows are with the same date
please help me to solve it
for example:
1 **2017-02-19** 15:12:20 1 0 1 0
1 **2017-02-19** 15:12:37 1 0 1 0
1 **2017-02-19** 15:12:41 1 0 1 0 Count:3
1 **2017-02-20** 15:14:10 1 2 1 0
1 **2017-02-20** 16:38:14 1 2 1 0
3 **2017-02-20** 16:38:19 1 2 1 0 Count:3
3 **2017-02-21** 16:39:09 1 0 1 0
3 **2017-02-21** 17:25:06 1 0 1 0
2 **2017-02-21** 18:28:50 1 0 1 0 Count:3
2 **2017-02-22** 18:29:04 1 0 1 0 Count:1
2 **2017-02-23** 18:29:17 1 0 1 0
3 **2017-02-23** 18:30:45 1 0 1 0 Count:2
2 **2017-02-24** 18:31:32 1 0 1 0
2 **2017-02-24** 18:31:47 1 0 1 0 Count:2
2 **2017-02-25** 18:32:18 1 4 1 0 Count:1
Of course I want date section not time include

var res = yourList.GroupBy(x => x.date.Date).Select(x=> new { date = x.Key, count = x.Count() });
This will create a new list containtng date and count of elements for each date.

Related

How to calculate count?

I want to calculate the count data from data table dt based on time and I have to store the counts on different variables.
Sample DB :
ID File_Name Uploaded_Time
----- --------- -------------
1 abc 3/18/2015 12:03:26 AM
1 abc 3/18/2015 12:10:26 AM
1 abc 3/18/2015 1:47:26 AM
1 abc 3/18/2015 2:17:52 AM
2 abc 3/18/2015 3:55:26 AM
1 abc 3/18/2015 6:12:44 AM
2 abc 3/18/2015 8:55:26 AM
2 abc 3/18/2015 10:55:26 AM
2 abc 3/18/2015 11:49:26 AM
1 abc 3/18/2015 12:55:26 PM
1 abc 3/18/2015 1:47:26 PM
1 abc 3/18/2015 2:47:26 PM
1 abc 3/18/2015 4:23:15 PM
1 abc 3/18/2015 6:47:26 PM
2 abc 3/18/2015 8:33:45 PM
Code :
protected void btnSubmit_Click(object sender, EventArgs e)
{
CommunicationTableAdapters.tbl_splited_detailsTableAdapter sd;
sd = new CommunicationTableAdapters.tbl_splited_detailsTableAdapter();
DataTable dt = new DataTable();
dt = sd.GetSiteUploadDetails(ddlSiteID.SelectedValue, txtDate.Text);
foreach (DataRow row in dt.Rows)
{
if (dt.Rows.IndexOf(row) != 0)
{
string uplodedtime = (row["Uploaded_Time"].ToString());
}
}
}
Example :
Calculate the count in between 12:00:00 AM to 1:00:00 AM and store in a variable. Like this I want to calculate 24 hrs count and store in 24 variable.
From the above sample DB, the required output is
variable count
-------- -----
hour1 2
hour2 1
hour3 1
hour4 1
hour5 0
hour6 0
hour7 1
hour8 0
hour9 1
hour10 0
hour11 1
hour12 1
hour13 1
hour14 1
hour15 1
hour16 0
hour17 1
hour18 0
hour19 1
hour20 0
hour21 1
hour22 0
hour23 0
hour24 0
This should do it:
var result =
dt.AsEnumerable()
.GroupBy (x => x.Field<DateTime>("Uploaded_Time").Hour)
.Select (x => new { Hour = x.Key, Count = x.Count() });
And if you want to to get a 0 for non existing values use the above expression with:
result = from hour in Enumerable.Range(0, 24)
join item in result on hour equals item.Hour into g
from item in g.DefaultIfEmpty()
select new
{
Hour = hour == 0 ? 24 : hour,
Count = item == null ? 0 : item.Count
};
Since the data is already sorted on the basis of upload time so what you could do is take 5 variables and read each query from the upload time colm.
1st var mon = string till first '/'
2nd var day = string between first '/' and second '/'
3 rd var for year
4th variable for the hour time
and 5 th variable for a look ahead hour time
So in your ques it would be for first query
day = 18
mon = 3
year = 2015
hour_initial = 12
hour_ahead = 12
and increment count till the hour_ahead changes or the day changes.(which ever comes first) and upload count for that specific hour
Then change the hour_intial to next hour and continue the process.....
(this is the basic technique)

Datatable.Select with max(col) and WHERE clause?

I have a datatable with the following data.
Week Score Rank
1 75.8300000000 1
2 76.6800000000 9
3 79.8787870000 4
4 0 0
5 0 0
6 0 0
7 0 0
...
53 0 0
If the datatable only had the first 3 weeks (weeks with Rank), then the following line would work perfectly. But now I need to add a WHERE clause that gets MAX(Week) where Score is greater than 0. In this case, the row returned would be Week 3. Essentially, the query would be SELECT max(week) From datatable where Rank > 0
DataRow[] dr = dsRanks.Tables[0].Select("Week = MAX(Week)");
I tried the following, but I get an index error because 0 rows are returned.
DataRow[] dr = dsRanks.Tables[0].Select("Week = MAX(Week) and Rank > 0");
Any help is appreciated.
Thanks.
It's easier to solve using LINQ instead:
var week = dsRansk.Tables[0].AsEnumerable()
.Where(row => row.Field<int>("Rank") > 0)
.Max(row => row.Field<int>("Week"));
It looks to me that you want the data row with the highest numbered week that has valid data. Something like this should do it:
var dr = dsRanks.Tables[0].Select("Rank > 0", "Week ASC"). LastOrDefault();
As per your example dr is the data row for Week 3.

Put value in datatable group by month

I have this datatable in c#
Date Employee Job1 Job2 Job3
1/1/2012 a 1 1 1
1/1/2012 b 2 2 2
1/1/2012 c 2 1 4
1/1/2012 d 4 2 1
1/2/2012 a 3 2 5
1/2/2012 b 2 2 2
1/2/2012 c 3 3 3
1/2/2012 d 1 1 1
1/3/2012 a 5 5 5
1/3/2012 b 2 2 6
1/3/2012 c 1 1 1
1/3/2012 d 2 3 4
2/1/2012 a 2 2.5 2
2/1/2012 b 5 5 2
2/1/2012 c 2 2 2
2/2/2012 a 3 3 3
2/2/2012 b 2 3 3
3/1/2012 a 4 4 11
3/5/2012 a 14 42.5 15
3/6/2012 a 21 12.143 22
3/8/2012 a 8.9 45 27
3/8/2012 b 4.4 25 31
I want to loop through the values monthwise such that i can store the value in a datatable and will do the other calculation with that. Here with this example it will have three datatable, first with january values, another one with feb and last one with march rows. How can this be done by Linq. Please suggest the Linq syntax which will group the results month wise.
var monthEmpGroups = dt.AsEnumerable()
.Select(r => new
{
Year = DateTime.Parse(r.Field<string>("DATE")).Year,
Month = DateTime.Parse(r.Field<string>("DATE")).Month.ToString()
})
.GroupBy(x => x.Month);
var dtf = CultureInfo.CurrentCulture.DateTimeFormat;
foreach (var empGroup in monthEmpGroups)
{
int month = int.Parse(empGroup.Key);
string colName = dtf.GetMonthName(month);
// Here i want to get all the rows where month is colName (i.e.january, feb, march)
}
Please suggest if there is other way around to get the values month wise using LINQ.
You should move getting items for every group into monthEmpGroups query:
var monthEmpGroups = (from r in dt.AsEnumerable()
let month = DateTime.Parse(r.Field<string>("DATE")).Month
group r by month into g
select new { Month = g.Key, Items = g.ToList() });
With that you can easily get desired results:
var dtf = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat;
foreach (var empGroup in monthEmpGroups)
{
int month = empGroup.Month;
string colName = dtf.GetMonthName(month);
List<DataRow> items = empGroup.Items;
}

Update all records using a function sql

I am looking to update a calculated sum in sql
Basically I have a table:
ImportID SeiralNumber Day Hour value Difference Complete
1 123 1 1 6 NULL 0
2 123 1 2 8 NULL 0
3 123 1 5 21 NULL 0
4 123 1 6 28 NULL 0
5 222 2 2 12 NULL 0
6 222 2 5 18 NULL 0
7 222 2 4 16 NULL 0
8 222 1 12 8 NULL 0
For each serial number there will be a day 1-365 and hour through 1-12, all I want to do is calculate the difference filed from the record before
So take ImportID 6, I need to get the record which is on the same day and the hour before (importID 7) then I need to update the Difference using the value field which is 18 -17 = 1.
N.B. There may be gaps in the sequence and if there is no previous record then the difference should stay as NULL. Once they have been calculated they need to be inserted into a new table only when the difference is now not null and it doesn't exist in the table already, on a successful insert they get marked as complete. Also a record before can be a previous day (day 1 hour 12) is the record before (day 2, hour 1)
Currently I am using a loop to select the null values, get the previous record, update the record, if its OK insert into other table, update the Completed field.
My issue is that this is working on a million records and it is taking a long while to Select the applicable records (completed = 0) into a temp table and loop through each.
Is there any quicker way to mass process these as an update statement? Or separate statements?
The result should be
ImportID SeiralNumber Day Hour value Difference Complete
1 123 1 1 6 NULL 0
2 123 1 2 8 2 1
3 123 1 5 21 NULL 0
4 123 1 6 28 7 1
5 222 2 1 12 4 1
6 222 2 5 18 2 1
7 222 2 4 16 NULL 0
8 222 1 12 8 NULL 0
Thanks in advance
I think this is basically it isn't it?
DECLARE #TABLE TABLE
(
ImportId INT,
SerialNumber INT,
Day INT,
Hour INT,
Value INT,
Difference INT,
Complete INT
)
INSERT INTO #TABLE VALUES
(1,123,1,1,6,NULL,0),
(2,123,1,2,8,NULL,0),
(3,123,1,5,21,NULL,0),
(4,123,1,6,28,NULL,0),
(5,222,2,1,12,NULL,0),
(6,222,2,5,18,NULL,0),
(7,222,2,4,16,NULL,0),
(8,222,1,12,8,NULL,0)
SELECT * FROM #Table
UPDATE T
SET T.Difference = T.Value - TT.Value,
Complete = 1
FROM
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY SerialNumber ORDER BY Day ASC, Hour ASC) AS RowCounter
FROM #TABLE
WHERE Complete = 0 --Ignore completed ones
)AS T
INNER JOIN
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY SerialNumber ORDER BY Day ASC, Hour ASC) AS RowCounter
FROM #TABLE
)AS TT
ON T.SerialNumber = TT.SerialNumber
WHERE
(
T.RowCounter = TT.RowCounter + 1
AND
T.Day = TT.Day
AND
T.Hour = TT.Hour + 1
)
OR
(
T.Day = TT.Day + 1
AND
T.Hour = 1
AND
TT.Hour = 12
)
SELECT * FROM #TABLE

Copy/paste Data from 1 sheet to another by matching specific cell or data (Date)

I have two sheets in Excel. Sheet2 contains data and I need that is on per date for 1 month, I would like to copy/paste the data on sheet1 by matching the date I put on the Blank date, example: Put Oct 1 on the date of sheet1 it will automatically copy the data of Oct 1 on sheet2. put Oct 2 copy data on Oct 2 an so on..
SHEET 1
DATE
Turnover IN out Revenue
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
SHEET 2
1-Oct 2-Oct
Turnover IN OUT RESULT Turnover IN OUT RESULT
14599 4410 4500 -90 1000 54641 737542 -90
67530 9330 1440 7890 100 345 4274 7890
57699 11520 2673 8846 500 4525 275274 8846.5
196425 55960 68800 -12840 60050 42 4247 -12840
92100 17770 2500 15270 136450 4 14 15270
well, to copy certain range(with cell content, ...) you should try following, for example:
Excel.Range selCell1 = ((Excel.Worksheet)Application.ActiveSheet).Range["A1", "CA2000"];
Excel.Range selCell2 = ((Excel.Worksheet)Application.Sheets[2]).Range["A1", "CA2000"];
selCell1.Copy(selCell2);
Do you need a C# solution? Otherwise you can easily construct this type of thing directly in the excel spreadsheet:
=INDEX($11:$20,ROW(),MATCH($A$1,$11:$11,0)+COLUMN()-1)
Good Luck.

Categories

Resources