Searching data by date - error - sql

I'm using my VB.Net program to query a database in MS Access. In the database, I have a table that contain a "question_start" (Date/Time) field.
I would like to return the IDs of each record that occur on or after a date that I choose in my VB programme.
The data in the Access table, is being stored as Date/Time under a General Date format (e.g. '10/10/2016 15:48:01').
In VB.NEt, I am using the DateTimePicker object to select the date.
Below is the code I'm using to bring back all records that have a Start Date of 10/10/2016 (10th October 2016).
(Note 1: I have removed the time element from this particular search as I do not need my results to be time-sensitive here but are required later.)
Private Sub btnDateText_Click(sender As Object, e As EventArgs) Handles btnDateText.Click
Dim dt_QuestionDate As New DataTable()
dt_QuestionDate = getData("SELECT question_id
FROM tblQuestion
WHERE question_start => " & dtDateText.Value.ToString("dd-MM-yyyy") & ""
)
lstDateText.DataSource = dt_QuestionDate
lstDateText.DisplayMember = "question_id"
lstDateText.ValueMember = "question_id"
End Sub
**There are records in my database that should be returned, but I am receiving no values currently. I am not sure if it is how I've written the WHERE clause (I've done WHERE with "=>", ">=", and also "=") but I am not receiving records with the 10/10/2016.
Has anyone any ideas please? I don't know if it's because it's a simple mistake, or because of the time element that is stored in Access?

You need proper formatting of the string expression for the date value:
WHERE question_start => #" & dtDateText.Value.ToString("yyyy'/'MM'/'dd") & "#"

Related

Displaying a field associated with a max date value record

I am working on an MS Access database and have been trying to get an unbound field on a main navigation form to display the LastUserChange that is associated with the record that was last updated.
I have used DMax() to identify the record that was most recently updated, but I can't seem to get the user ID associated with that record to display. I have a field in the table with the date timestamp that stores the user ID with it, so the data is saved in the same table. The code that I have been working on is as follows:
Private Sub Form_Load()
Dim strSQL As String
strSQL = "SELECT tblstatusupdate.LastUserChange" & _
"FROM tblstatusupdate " & _
"WHERE tblstatusupdate.LastChangeDate = DMax("LastChangeDate", "tblStatusUpdate")"
DoCmd.RunSQL strSQL
Me.LastUpdateBy = strSQL
End Sub
The code that I used to get the date of the most recently updated record is:
= DMax("LastChangeDate", "tblStatusUpdate")
Can someone please help me?
Often a mistake of new users in MS Access, DoCmd.RunSQL is reserved for action queries (i.e., INSERT, DELETE, UPDATE, ALTER, CREATE) and not SELECT queries that return a resultset.
However, for your needs consider running nested domain functions in VBA without any SQL calls. DLookUp looks up user with the criteria that its change date matches the max value of table using Dmax. Date literals must be enclosed with # characters and not quotes.
Me.LastUpdatedBy = DLookUp("LastUserChange", "tblStatusUpdate", "LastChangeDate = #" _
& DMax("LastChangeDate", "tblStatusUpdate") & "#")

SQL: Compare Date Range in a String text field

I have an MS Access db. I am writing an application in C# to access it. I have a field "FileName" of type "Short Text in MS Access. Data in FileName field is like "Test 11-12-2004 15.11.15".
Using a Date Range, I got to search records based on FileName field. I am not able to get - How do I compare the date of this format and retrieve the records ? FileName is a Text type and date is a substring of it. Retrieving only the date part and comparing with >= beginDate && <= endDate seems like a puzzle to me.
Can anyone suggest how do I write SQL query to perform this date range comparision and retrieve those records - "Select * from TestHead where FileName......" ????
Any help is appreciated.
Thanks a lot,
In your C# code, as you are going through the records, I'd split the string like this:
char[] delimiters = {' '};
string[] FileNameParts = FileName.Split(delimiters);
This will result in an array FileNameParts, the second element of which will contain the date, which you can convert to an actual date for use in the query:
DateTime FileNameDate = Convert.ToDateTime(FileNameParts(1))
Something along the lines of:
sSQL = "SELECT * FROM Table WHERE " & beginDate & " <= " & FileNameDate
I see this as preferable to adding a column to your table that contains the date substring of the FileName field, because then you constantly need to be updating that column whenever existing records are modified or new records are added. That means more clutter on the C# side, or an UPDATE query on the Access side which at least needs to get called periodically. Either way it would be more communication with the database.

Best way to extract rows from DataTable (based on date field) and copy to another DataTable

I have a DataTable containing about 30 rows and I need to extract all rows having a date field bigger than a date stored into a variable.
(This code will be executed a lot of times)
I found three ways to do this but I would like to know how to choose because I don't know the differences between various codes.
Here is what I was able to write (and my worries):
1st way (DataTable.Select)
Dim SelectedRows() As DataRow = DT_DBData.Select("In_Date=#" & _
LastDate.ToString("yyyy-MM-dd") & "#")
Using New_Dt As DataTable = SelectedRows.CopyToDataTable
'Some code
End Using
I'm worried about the string format: I'm afraid that some rows may be not extracted because of a date formatting error.
2nd way (query Linq)
Using New_Dt As DataTable = (From DBData In DT_DBData.AsEnumerable() _
Where DBData.Field(Of Date)("In_Date") >= LastDate).CopyToDataTable
'Some code
End Using
I never used Linq and so I don't know what kind of issues can it give me.
3rd way (For Each Loop + If Then)
Using New_Dt As DataTable = DT_DBData.Clone
For Each dr As DataRow In DT_DBData.Rows
If dr("In_Date") >= LastDate Then
New_Dt.Rows.Add(dr.ItemArray)
End If
Next
'Some code
End Using
I'm not really worried about this code. I only think that the others could be better or faster (but I can't answer to this)
Faster is kind of irrelevant when dealing with 30 rows.
The first one is kind of wasteful. You start with a DataTable, Select to get a subset, then convert the result into a new DataTable. Time to extract matching Rows: 8 ms.
You can work with the SelectedRows array without putting it into a new DataTable. If it goes back to the DB after "some code", I would not extract it from the DT.
By the way, there is no reason to worry about matching date formats as long as the DB column is a date type (and therefore, the DataTable column will be also). Dates do not have a format; formats are just how computers (and by extension, us) display them to users.
Dim drs = dt.Select(String.Format("StartDate > '{0}'", dtTgt.Date), "")
The date type I pass will compare/filter just fine with the DateTime data for that column. Formats only come into play when you convert them to string, which is mostly only needed for those pesky users.
One option you missed might be especially useful if this will be done over and over: A DataView:
dt.Load(cmd.ExecuteReader)
' create dataview
Dim dv As New DataView(dt)
dv.RowFilter = String.Format("StartDate > '{0}'", dtTgt.Date)
dv.Sort = "StartDate asc"
' show/iterate/whatever
dgv.DataSource = dv
If the data goes back to the DB, using this method, the rows will retain all the rowstate values.

How to get records between two dates in vb.net?

All ...
I need to display records that are between the two dates passed in from DateTimePickers.
I am getting records that are NOT in between the dates that I specified from vb.net.
Please go through the code shown below....
Following is the code :
Private Sub btn_Show_Inquiry_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_Show_Inquiry.Click
report_viewer_form.Report_viewer_CrystalReportViewer1.ReportSource = Nothing
report_viewer_form.Report_viewer_CrystalReportViewer1.Refresh()
str1 = "SELECT * FROM Inquiry_Details WHERE Inquiry_Date>=#" & dtp_inq_from.Text & "# AND Inquiry_Date<=#" & dtp_inq_to.Text & "#"
If dtp_inq_from.Text > dtp_inq_to.Text Then
MessageBox.Show("FROM_DATE Must Be Less Then TO_DATE.", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Exit Sub
End If
If cn.State <> ConnectionState.Open Then
cn.Open()
End If
da = New OleDbDataAdapter(str1, cn)
report_dataset = New DataSet
da.Fill(report_dataset, "table2")
If MsgBox("Do You Want to Print Report ?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
report_viewer_form.Show()
Dim cr As New ReportDocument
cr = New Inquiry_CrystalReport
cr.SetDataSource(report_dataset.Tables("table2"))
report_viewer_form.Report_viewer_CrystalReportViewer1.ReportSource = cr
End If
End Sub
Your problem seems to be in the way you parse passed date parameters to the query and they're probably not in format that Access would recognize as a valid Date type. Try with CDate() function to let Access parse your input values to its internal date type properly. It will accept any valid date expression:
Any expression that can be interpreted as a date, including date
literals, numbers that look like dates, strings that look like dates,
and dates returned from functions. A date expression is limited to
numbers or strings, in any combination, that can represent a date from
January 1, 100 – December 31, 9999.
Your code could thus look like this:
str1 = "SELECT * FROM Inquiry_Details WHERE Inquiry_Date>=CDate('" &
dtp_inq_from.Text & "') AND Inquiry_Date<=CDate('" &
dtp_inq_to.Text & "')"
Another function that you might want to try (if CDate won't cut it) is DateValue():
The required date argument is normally a string expression
representing a date from January 1, 100 through December 31, 9999.
However, date can also be any expression that can represent a date, a
time, or both a date and time, in that range.
The success of these two functions might also depend on input date formatting and system locale.

Checking for date overlap across multiple date range objects

I have several records in a database that have Start and End Dates
09/15/2011 - 09/30/2011
10/15/2011 - 10/22/2011
11/01/2011 - 11/15/2011
When user stores a record, I need to make sure dates don't overlap.
My simple code checks date ranges within a specific record (e.g. user enters 9/16/2011 or 10/21/2011, I throw an exception.)
But, on the slim chance a user gets creative (e.g. 10/14/2011 - 10/23/2011 or even 10/14/2011 to 11/16/2011), now they have circumvented my check.
BTW, the user could enter 10/14/2011 to 10/23/2011 if they were editing the record that contained values 10/15/2011 - 10/22/2011.
So, I'm trying to solve this riddle with a linq query. However, what I have isn't working exactly right.
UPDATE Nevermind about code not working. While trying to provide an example to expand on Miika's repsonse, I found my answer. So, giving credit to Miika for pointing me in the right direction and posting my working code below:
Here's my code:
Private Sub CheckForOverlap(myMonth As Messages.MyMonth)
Dim am As New MyMonth()
Dim amCollection As Messages.MyMonthCollection
Dim overlappingMyMonthDate As Boolean = False
Dim sErrorMsg As String = ""
'...non-applicable code omitted
Dim query = From s In amCollection _
Let s1 As MyMonth = CType(s, MyMonth) _
Where s1.AttendanceMonthID <> attendanceMonth.AttendanceMonthID And _
(CDate(attendanceMonth.StartDate) < CDate(s1.StartDate) And CDate(attendanceMonth.EndDate) > CDate(s1.EndDate)) _
Select s1
If query.Count > 0 Then
sErrorMsg = "Dates entered surround another entry"
End If
If overlappingMyMonthDate Then
Throw New Exception(sErrorMsg)
End If
End Sub
End Class
It all came down a LINQ query.
Do you need to do it in code or would SQL be an option? If the data is in a database, you could use the following query to check for overlaps.
SELECT COUNT(*)
FROM Table1
WHERE Table1.StartDate < 'endCheckDate'
AND Table1.EndDate > 'startCheckDate'
This will return a count of the number of overlaps found. 'endCheckDate' and 'startCheckDate' are your new query values (in date format). If your data is in a object collection in memory, then you could use LINQ. If you need help with a LINQ statement, let me know.