How to convert Access statement to SQL to determine date range - sql-server-2012

I have an Access statement that I am trying to convert to be used in SQL Server 2012. Here is the statement:
>=DateAdd("m",-1,DateAdd("m",-12,Month(Now()) & "/" & [FiscalYear])) And <DateAdd("m",-1,DateAdd("m",-12,Month(Now()) & "/" & [FiscalYear]))+364
It is basically getting a rolling 12 month period. How can I use this in SQL or is there a better way to write this altogether?

Here's how you would get the past 12 months worth of data in SQL:
SELECT *
FROM Table
WHERE DateField > DATEADD(MONTH, -12, GETDATE())

Related

How to extract records from SQL table falling within certain date range? [duplicate]

I have a SQL statement to display data between two dates. I almost got it but there's a problem.
If I input March 1,2012 to March 7, 2012.. it should show data with dates between the two.. but it also show all of the dates under March 2012.. but whenever I input March 10, 2012 to March 30, 2012 the SQL works perfectly.. any help will be appreciated. thanks
SELECT
agentname, noofcalls, qualified, booking, resched,
actualbooking, sales, remarks,
concat(month,' ',day,',',year) as 'date'
FROM
tblagents
WHERE
(month between '" & cbosmonth.Text & "' AND '" & cboemonth.Text & "')
AND (day between '" & cbosday.Text & "' AND '" & cboeday.Text & "')
AND (year between '" & cbosyear.Text & "' AND '" & cboeyear.Text & "')"
you are doing string comparisons in each of your 'between'. Every number starting with a 1, a 2 or a 3, regardless of what follows it, i.e. 21, or 26, or 31, they are all lower than 7 if you look at them as strings. 1 to 30 works because you're only leaving 31 behind, and 30 < 31 as a String as well.
Do the concatenation first and then the between:
WHERE concat(month,' ',day,',',year)
BETWEEN concat(cbosmonth.Text,' ', cbosday.Text,' ',cbosyear.Text)
AND concat(cboemonth.Text,' ', cboeday.Text,' ',cboeyear.Text)
(check out for correct syntax, I'm just copy pasting from your question, not tried it)
BTW, unless you have a reason to, you probably should be storing the entire date in a single column with the right data time (datetime, timestamp, ...) and not three separated columns.
That is the incorrect way to store a date in database.
Change the date column to datatype date.
You could then do:
SELECT *
FROM table
WHERE bookingDate between to_date ('2012/03/01', 'yyyy/mm/dd')
AND to_date ('2012/03/07', 'yyyy/mm/dd');
This approach is wrong.
In order for a date to be between two interval dates it does not have to have a day number between the two dates, e.g. (pseudocode)
date = May-25-2012; startDate = March-15-2012, endDate = June-01-2012
date is clearly between startDate and endDate, yet
day(date) is 25, which is not between day(startDate) = 15 and day(endDate) = 1
more, as 15 is larger than 1, there are no numbers between them, so that condition will always be false
Similar example can be made for the month part of the date (e.g. date = May-25-2012; startDate = September-15-2010, endDate = Match-01-2015)
You need to take the values for day, month, year, and construct a Date either in the application or on the server and use that to compare the values against.
To make a date from text fields in VB
Dim startDate = new DateTime(
Convert.ToInt32(cbosyear.Text),
Convert.ToInt32(cbosmonth.Text),
Convert.ToInt32(cbosday.Text))
Note that this will fail if the user enters, e.g. "some text" for the year value. You'll need to add some data validations to achieve that.
To make a datetime from parts in SQL Server, take a look here, there are quite a few techniques explained.
Also, you should always avoid just pasting values into the sql string, that's asking for sql injection problems. You should do something like this:
Dim command = new SqlCommand()
command.CommandText = "SELECT .... FROM tblagents where DATEFROMPARTS(year, month, day) between #startDate AND #endDate"
command.Parameters.AddWithValue("#startDate", startDate)
command.Parameters.AddWithValue("#endDate", endDate)

SELECT * FROM MyTable WHERE [Date] = ([Date] + 8 hours)

My problem starts with the fact that my server is in a totally different country, so we have a difference of 8 hours (GMT).
So when I'm trying to do something like this:
CreateNewDataSet("SELECT * FROM tblArchives WHERE [Date] =" & DateAndTime.Today.Date.ToString("MM/dd/yyyy") & "'; & , "tblArchives")
It won't get all the results because it happened today in my country but yesterday where the server is based.
I tried unsuccessfully to use the DATEADD function.
Is there any way to do something like:
SELECT FROM WHERE [DATE+8 hours] =DateAndTime.Today.Date.ToString("MM/dd/yyyy")
Why don't you subtract the hours from the other side of the condition statement:
CreateNewDataSet("SELECT * FROM tblArchives WHERE [Date] =" & DateAdd(DateInterval.Hour, -8, DateAndTime.Today.Date).ToString("MM/dd/yyyy") & "'; & , "tblArchives")
You could move the date calculation in to the SQL so that you get the servers date something like
SELECT * FROM tblArchives WHERE Date = DateAdd(HH, +8,getdate())
try to run DateAdd(HH, +8,getdate()) to see the actual date and time it uses in your query. I have similar needs but I always set the time to be 1 millisecond after midnight to one millisecond before midnight. This will make sure you get all the data for a particular day.
you have to use DateTime.AddHours method
"SELECT * FROM tblArchives WHERE [Date] =" &
DateAndTime.Today.AddHours(-8).ToString("MM/dd/yyyy")
Instead of adding +8 hours to [Date] Column, add -8 to the current server date

query to select data from this day [duplicate]

This question already has answers here:
In SQL Server, what is the best way to filter items for an entire day
(3 answers)
Closed 8 years ago.
I have a database table that has Datelogged columns from type Datetime (Sql server 2008 r2)
The Datelogged value is like this 2014-10-22 12:57:36.583
I want to do a query to select all the rows that its date is today (I care about year, month, and day) but not (hour, second.)
This is my query
string query = "SELECT * FROM Orders WHERE PrintTime is NULL WHERE Datelogged = #Datelogged";
but I didn't know what should I do to tell the query to compare just on year-month-day
Based on #Aaron Bertrand comment
It appears that it is better to use a Date Range from current day midnight (00:00:00) to < tomorrow at midnight.
Query copied from his comment.
DateLogged >= CONVERT(DATE, #DateLogged) AND
DateLogged < DATEADD(DAY, 1, CONVERT(DATE, #DateLogged))
Also see: Bad habits to kick : mis-handling date / range queries By Aaron Bertrand
(Old Answer)
You can use CONVERT(DATE, Datelogged) to get Date part without time.
"SELECT * FROM Orders WHERE PrintTime is NULL AND CONVERT(DATE, Datelogged) = #Datelogged"
Make sure you pass the parameter value using Date property in C# like:
cmd.Paramaters.AddWithValue("#Datelogged", DateTime.Today);// or DateTime.Now.Date
Also make sure to remove multiple WHERE from your query and use AND or OR to combine two conditions depending on your requirement.
Get the minimum date time range for current date and maximum date time range for today. Then, compare it with the logged date value.
Conversion operator on any table column adds extra conversion overhead and leads to inefficient use of index. Should be avoided when possible.
SELECT * FROM Orders
WHERE PrintTime is NULL
AND (Datelogged > dateadd(DD, -1, cast( GETDATE() as date)) AND Datelogged < dateadd(DD, 1, cast( GETDATE() as date)));

Convert custom numeric datevalue to real date in sql query

I have an application that comes with its own database and there is nothing I can change on that configuration. However we do pull data from the database to generate reports on.
For some reason (which I don't quite grasp), the application stores dates as the following number:
numdate = (int) '1' & <last two digits of year> & <zero-leading month> & <zero-leading day>
eg:
08/10/2008 -> 1081008
01/01/2014 -> 1140101
27/02/2014 -> 1140227
For now I just pull in the number and convert it on the go to a real date.
Is it possible to do this conversion via the sql query somehow?
If it's SQL Server, the following should work:
DECLARE #dateInt INT = 1981008
SELECT CONVERT(DATETIME, SUBSTRING(CONVERT(VARCHAR, #dateInt), 2, 6), 12)
To save you reading the comments, Gunther improved the performance by removing the substring operation in favour of subtraction:
SELECT CONVERT(DATETIME, CONVERT(VARCHAR,#dateInt-1000000), 12)
You could use this if you are using C#.
string dateString = "1981008";
DateTime dt;
DateTime.TryParseExact(dateString.Remove(0,1), "yyMMdd", null, System.Globalization.DateTimeStyles.None, out dt);
In SQL (assuming it is MS SQL), try this:
convert(datetime,'981008',112)

BETWEEN clause in SQL

I have a SQL statement to display data between two dates. I almost got it but there's a problem.
If I input March 1,2012 to March 7, 2012.. it should show data with dates between the two.. but it also show all of the dates under March 2012.. but whenever I input March 10, 2012 to March 30, 2012 the SQL works perfectly.. any help will be appreciated. thanks
SELECT
agentname, noofcalls, qualified, booking, resched,
actualbooking, sales, remarks,
concat(month,' ',day,',',year) as 'date'
FROM
tblagents
WHERE
(month between '" & cbosmonth.Text & "' AND '" & cboemonth.Text & "')
AND (day between '" & cbosday.Text & "' AND '" & cboeday.Text & "')
AND (year between '" & cbosyear.Text & "' AND '" & cboeyear.Text & "')"
you are doing string comparisons in each of your 'between'. Every number starting with a 1, a 2 or a 3, regardless of what follows it, i.e. 21, or 26, or 31, they are all lower than 7 if you look at them as strings. 1 to 30 works because you're only leaving 31 behind, and 30 < 31 as a String as well.
Do the concatenation first and then the between:
WHERE concat(month,' ',day,',',year)
BETWEEN concat(cbosmonth.Text,' ', cbosday.Text,' ',cbosyear.Text)
AND concat(cboemonth.Text,' ', cboeday.Text,' ',cboeyear.Text)
(check out for correct syntax, I'm just copy pasting from your question, not tried it)
BTW, unless you have a reason to, you probably should be storing the entire date in a single column with the right data time (datetime, timestamp, ...) and not three separated columns.
That is the incorrect way to store a date in database.
Change the date column to datatype date.
You could then do:
SELECT *
FROM table
WHERE bookingDate between to_date ('2012/03/01', 'yyyy/mm/dd')
AND to_date ('2012/03/07', 'yyyy/mm/dd');
This approach is wrong.
In order for a date to be between two interval dates it does not have to have a day number between the two dates, e.g. (pseudocode)
date = May-25-2012; startDate = March-15-2012, endDate = June-01-2012
date is clearly between startDate and endDate, yet
day(date) is 25, which is not between day(startDate) = 15 and day(endDate) = 1
more, as 15 is larger than 1, there are no numbers between them, so that condition will always be false
Similar example can be made for the month part of the date (e.g. date = May-25-2012; startDate = September-15-2010, endDate = Match-01-2015)
You need to take the values for day, month, year, and construct a Date either in the application or on the server and use that to compare the values against.
To make a date from text fields in VB
Dim startDate = new DateTime(
Convert.ToInt32(cbosyear.Text),
Convert.ToInt32(cbosmonth.Text),
Convert.ToInt32(cbosday.Text))
Note that this will fail if the user enters, e.g. "some text" for the year value. You'll need to add some data validations to achieve that.
To make a datetime from parts in SQL Server, take a look here, there are quite a few techniques explained.
Also, you should always avoid just pasting values into the sql string, that's asking for sql injection problems. You should do something like this:
Dim command = new SqlCommand()
command.CommandText = "SELECT .... FROM tblagents where DATEFROMPARTS(year, month, day) between #startDate AND #endDate"
command.Parameters.AddWithValue("#startDate", startDate)
command.Parameters.AddWithValue("#endDate", endDate)