Filter datatable between two dates - c#

I have a column within my database called "Month". What i want to do is filter the table between two months. Example of this is March - June. I have code which works BUT only works alphabetically
string strquery = "select * from tbl_DR_data ";
string strq2 = "where";
if (DropDownList6.SelectedItem.Text != "All" && DropDownList8.SelectedItem.Text != "All") {
string month1 = DropDownList6.SelectedItem.Text.ToString();
string month2 = DropDownList8.SelectedItem.Text.ToString();
strq2 = strq2 + "[Month] BETWEEN'" + month1 + "'AND'" + month2 + "'";
}
When DropDownList6 = March and DropDownList8 = June. Nothing appears in the gridview which im binding BUT if the swap them around so DDL6= June and DDL8 = March it works :S
Is there a work around so that i can have the months ordered in how the months are meant to be instead of being alphabetical

why are you really storing months as strings in the database?, if you follow that path, trust me you are even going to encounter much more serious problems down the road & they will be a hell to debug. You can always get the month part from any date or dateTime column value.

try this code, Hope this what you expected
SET #FromMonth = 'March'
SET #ToMonth = 'June'
SELECT
*
FROM
tbl_DR_data
WHERE
DATEPART(mm,CAST([Month]+ ' 1900' AS DATETIME)) >= DATEPART(mm,CAST(#FromMonth+ ' 1900' AS DATETIME))
AND DATEPART(mm,CAST([Month]+ ' 1900' AS DATETIME)) <= DATEPART(mm,CAST(#ToMonth+ ' 1900' AS DATETIME))

This is the MSDN Syntax for BETWEEN
test_expression [ NOT ] BETWEEN begin_expression AND end_expression
Why no results when When DropDownList6 = March and DropDownList8 = June?
With above values, your query becomes like
[Month] BETWEEN 'March' AND 'June'
Unfortunately, when you are filtering using BETWEEN, begin_expression should be less than or equal to end_expression. In your case, since you have stored months (names) as string in the database, March comes after June in alphabetical order and so above condition returns false and no results.
This is a fiddle example same as yours with no results.
You can get the month from a date/datetime field using various methods. In sql server, you can use;
//Month NUMBER
month(datefield) as month_Number
//Month NAME
datename(month,datefield) as month_Name
Just to give you worst side of your design. Just check the results of filtering by where month between 'april' and 'may'.
Your results include: August, December, February, January, July, June, March
Solution:
For the time since you don't have full date, I guess it would be better to update your database filed as below and change the datatype of [month] to int type;
update yourTable
set [month] = case [month] when 'January' then 1
when 'February' then 2
...
when 'December' then 12 end
Now change the data type of [month] to int type and then pass the month number from the code as
[month] BETWEEN 3 and 6
Also, try to avoid key words such as Month for field names.

I am not sure what your DB design is or even what the Month Fields data-type is, I agree with other first & foremost that this is not a good design as i cant think of a scenario where i can search only based on month. This should be a complete date fields.
It can give us better idea if you give us very brief about this functionality like where you want to use it & purpose.
Please don't take me as a critic... more details about your project can help us better understand & recommend solution. May be i am wrong as i may have not understand your question.
You can use nice solution given but think for the road ahead..

Related

How can I query UTC-dates for the client's current day?

My goal is to query the database for entries of the current day. Let's say the user saves a row with a time of '2021-01-27 01:00' and one with '2021-01-27 00:59'. The time zone is GMT+1 so it will be stored in the database in UTC like this:
row1: '2021-01-27T 00:00Z'
row2: '2021-01-26T 23:59Z'
How can I query for rows of the 27th of January 2021 (selectedUtcDate), from the view of the client / client?
The following will only return one entry:
.Where(row => row.Date == selectedUtcDate)
Do I have to use a range to get all entries of the same date?
.Where(row => row.Date >= selectedUtcDate && row.Date < selectedUtcDate.AddDays(1))
Or is this even automatically resolved by entity framework?
This has nothing to do with a database. The problem is, that the 24 hours or January 27th in Beijing are not the same 24 hours in Greenwich.
Internally, you use UTC. If somewhere on a computer in Beijing a date in local time is known, you know the start DateTime of that day and the start DateTime of the next day. After that you can convert these DateTime value to UTC:
DateTime localDay = FetchDateInLocalTime(); // The day in Beijing
DateTime utcDayStartTime = localDay.Date.ToUniversalTime;
DateTime utcNextDayStartTime = utcDayStartTime.AddDays(+1);
Now comes the database part:
var result = dbContext.Orders.Where(order => utcDayStartTime <= order.Date
&& order.Date < utNextDayStartTime);
Simple comme bonjour!
So to answer the original question with help of the comments:
Yes you have to use a range to query dates like this.
And of course you need to use the client's local date converted to utc (or the offset) as Harald Coppoolse mentioned.

Given a date range, find events that overlap within that range

Given a input date range, such as 11/1/2015 - 11/15/2015, what is the most efficient way to determine which events(CalendarEvents) are going on during that given date range.
event eventStart eventEnd
==================================
expo 10/25/2015 11/4/2015 //This should be selected.
concert 11/4/2014 11/5/2015 //This should be selected.
exhibit 11/15/2015 12/1/2015 //this should be selected.
display 10/26/2015 10/29/2015 //this should NOT be selected.
Linq or SQL server would be awesome. Basically given a date range, find events that overlap within that range.
I know I could "brute force" with a bit of code, just wondering if I'm missing something more elegant?
You can use StartA <= EndB AND EndA >= StartA to get the overlapping dates:
DECLARE #startDate DATE = '20151101',
#endDate DATE = '20151115'
SELECT *
FROM CalendarEvents
WHERE
eventStart <= #endDate
AND eventEnd >= #startDate
SQL Fiddle
Reference

How to assign yesterday's date to a parameter C#

I have a C# program that will run as a windows scheduled task. This program will load, run a SQL Query, email the results stored in the dataset, and then close. I have everything except the using Yesterdays date.
Here is my current Query:
SELECT Store_Id, Paid_Out_Amount, Paid_Out_Comment, Paid_Out_Datetime, Update_UserName, Till_Number, #startdate AS Start, #enddate AS Today
FROM Paid_Out_Tb
WHERE (Store_Id = 1929) AND (Paid_Out_Datetime BETWEEN #startdate AND #enddate)
Obviously I need to assign #startdate and #enddate at the time of the query. Since I will need 12AM to 1159PM that is the reason for the start and end. So for example. If I want to run the program today it would search yesterday (the 23rd) so #startdate would be assigned 7/22/12 00:00:00 and #enddate would be assigned 7/22/12 23:59:59...
Would it make more sense to do it in the query instead of the program? If so how would I change the query?
Slight improvement on the existing answers, to always get the start of yesterday without having to call the DateTime constructor.
var todayStart = DateTime.Today;
var yesterdayStart = todayStart.AddDays(-1);
var yesterdayEnd = todayStart.AddSeconds(-1); // Ick...
Note that this will use the current system time zone for the meaning of "today" - are you sure that's what you want? You may wish to consider using:
var todayUtcStart = DateTime.UtcNow.Date;
...
It's a shame that BETWEEN treats the end point as inclusive - if it were equivalent to
start <= value && value < end
then you could just give two midnight values, which would be a lot clearer.
Also note that while it wouldn't make interacting with the database any cleaner, for other uses of dates and times, you may wish to consider my Noda Time library, which contains a data type specifically for representing a date (and another for "time of day") etc. The aim is certainly to clarify code using dates and times. If it doesn't, I've failed!
You could calculate the start of yesterday in C#:
var yesterday = DateTime.Now.AddDays(-1);
var startOfYesterday = new DateTime(yesterday.Year, yesterday.Day, yesterday.Month);
com.Parameters.AddWithValue("#enddate", startOfYesterday);
If you're using SQL Server 2008+, you can change the datatype from datetime to date. The later can only store dates, so you won't have to worry about the datetime part.
Don't use between when dealing with date intervals. It is much easier and safer to use >= and <.
Something like this will give you yesterday stuff without parameters.
SELECT Store_Id, Paid_Out_Amount, Paid_Out_Comment, Paid_Out_Datetime, Update_UserName, Till_Number, #startdate AS Start, #enddate AS Today
FROM Paid_Out_Tb
WHERE Store_Id = 1929 AND
Paid_Out_Datetime >= dateadd(day, datediff(day, 0, getdate())-1, 0) and
Paid_Out_Datetime < dateadd(day, datediff(day, 0, getdate()), 0)
I assume you all looking for something this way
DateTime yesterdDaysDateTime = DateTime.Now.AddDays(-1);
You should always use parameterized queries.
In order to support what you are looking for you can drop in yesterdays date into a variable and pass that variable to your parameter.
This might also work, however with a performance drawback:
DateTime yesterday = DateTime.Today;
Thread.Sleep(1000 * 60 * 60 * 24);
You can also do this in SQL:
SELECT Store_Id, Paid_Out_Amount, Paid_Out_Comment,
Paid_Out_Datetime, Update_UserName, Till_Number, #startdate AS Start, #enddate AS Today
FROM Paid_Out_Tb
WHERE (Store_Id = 1929)
AND (Paid_Out_Datetime BETWEEN DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
AND dateadd(second, -1, DATEADD(dd, 1, DATEDIFF(dd, 0, GETDATE()))))
If you want to put in the query itself:
select (date_trunc('day', NOW()) - INTERVAL '1 day'); -- Yesterday Start
select (date_trunc('day', NOW()) - INTERVAL '1 second'); -- Yesterday End

get data from the last X minutes sqlite

I have this query:
SELECT who,whenAT
FROM seen
WHERE whenAT <= Datetime('now', '-5 minutes')
DateTimes stored in whenAT are formatted like this "10/12/2011 12:33:13 AM" whenAT is a TimeStamp.
that current query returns all records for some reason.
i'm inserting the datetime from code as DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") this is what is being saved into the table "10/12/2011 12:33:13 AM" i want to get all records within the last 5 minutes. everything i have tried either returns all records or no records.
Your query should be
SELECT who,whenAT FROM seen WHERE whenAT >= Datetime('now', '-5 minutes')
To get the last 5 minute, < will get everything besides the last 5 minutes
as Fatal510 said, you need to add the modifier 'localtime'
here some reference about datetime modifier https://www.sqlite.org/lang_datefunc.html
and here some example
SELECT who,whenAT FROM seen WHERE whenAT >= Datetime('now', '-5 minutes', 'localtime')
needed to add the modifier 'localtime'

How to calculate total working time in LINQ?

I have a table which holds clocking in/out records for every user :
RecID User In/Out ClockInOutTime
8 1 IN 25/02/2011 09:36:44
9 1 OUT 25/02/2011 11:36:44
10 1 IN 25/02/2011 12:36:44
11 1 OUT 25/02/2011 17:36:44
12 1 IN 26/02/2011 00:00:00
13 1 OUT 26/02/2011 12:00:00
14 1 IN 26/02/2011 09:00:44
15 1 OUT 26/02/2011 12:36:44
Any ideas how I can work out the total time worked for every month using LINQ?
cheers
SELECT (SELECT SUM(DATEDIFF(SECOND,[ClockInOutTime], GETDATE()))
FROM [swp].[dbo].[Table_1] t1
WHERE [In/Out] = 'IN'
AND t1.[User] = t.[User]) -
Coalesce((SELECT SUM(DATEDIFF(SECOND,[ClockInOutTime], GETDATE()))
FROM [swp].[dbo].[Table_1] t2
WHERE [In/Out] = 'OUT'
AND t2.[User] = t.[User]),0)
FROM [swp].[dbo].[Table_1] t
GROUP BY [User]
SQL way to solve this, not the best, but works even when last event don't have OUT timestamp i.e when last session still hasn't been closed.
This is non-trivial to do in either Linq or SQL. There is no easy way to link each OUT record with the corresponding IN record in SQL.
You have two options:
Querying the data and calculating in code within a for loop.
Changing the table schema like: RecID, User, ClockInTime, ClockOutTime
Option 1 is easy to implement, but I would seriously consider option 2. How do you define in your business rules that each IN record must be followed by a corresponding OUT record (or be last record)?
TimeSpan output = new TimeSpan(0,0,0);
using (var enumerator = input.GetEnumerator())
{
while (enumerator.MoveNext())
{
var begin = enumerator.Current.ClockInOutTime;
if(!enumerator.MoveNext())
break;
var end = enumerator.Current.ClockInOutTime;
output += (end - begin);
}
}
Yes, it isn't LINQ but I wanted to offer a solution - secondly, if the dates aren't alternating (so after an IN is always an OUT) it'll break.
There is no solution that will only use linq. This is due to the fact that you need to introduce error handling as well (if a user forgets to sign out, usually there is a maximum time that will be applied then etc).
I would group the data by user, order it by date time and then run through it in a for each and do the calculation within the for each.

Categories