I have a MySQL query that reads:
select sum(AmtPd) as HCSA from HC062017 where CostCenter = '8718' and ServiceDate > '08/31/2013'
Have been using it for several months with no problem. Today I encountered a problem with it not working. ServiceDate is a var(10) containing a date pulled from a report. The format is mm-dd-yyyy. What appears to be happening is if the ServiceDate is in 2013 (which some of them still are), then the statement works perfectly. However, when the ServiceDate is in 2014, no records are selected. If I leave off the ServiceDate parameter, I get the desired results (since all records this time are past the 08/31/2013 date). Maybe I lucked out with the months '09', '10', etc, falling after '08'. I've tried using str_to_date with no luck
select sum(AmtPd) as HCSA from HC062017 where CostCenter = '8718' and str_to_date(ServiceDate, '%m, %d, %Y') > '08-31-2013';.
Any suggestions on how to handle this?
You need to convert both to common format:
str_to_date(ServiceDate, '%m-%d-%Y') > str_to_date('08-31-2013', '%m-%d-%Y')
Comparing strings like you did is a bad idea. Strings are compared in alphabetic order, so '08-31-2013' is "smaller" than '09-30-2010' because 9 is compared to 8 before everything else. You can compare dates in ISO format YYYY-MM-DD.
STR_TO_DATE produces a date in a format of YYYY-MM-DD. So your date that you are comparing to must be in the same format:
str_to_date(ServiceDate, '%m, %d, %Y') > '2013-08-31';
Related
How can we insert date in in '17-DEC-80' format ?
How to find the last day of this month ?
like this I want to insert 10 dates in the given format and find the last day of the months specified in the date.
This can be acheived through the STR_TO_DATE and DATE_FORMAT internal functions.
You can insert a date so long as you accompany it with the format you are providing it in.
INSERT INTO DateFormats (DF_DATE_FIELD) VALUES (STR_TO_DATE('17-Dec-80', '%d-%b-%y'));
You can also SELECT a that same format date value with the DATE_FORMAT() function. To return the value you want from the table you would use
SELECT
DF_ID,
DF_DATE_FIELD,
DATE_FORMAT(DF_DATE_FIELD, '%d-%b-%y')
FROM DateFormats;
Assuming that DF_DATE_FIELD is in fact a DATE or DATETIME field. Also beware that this is case sensitive
The formatting is as follows
%d = Day of Month for 2 places (i.e 05, 12, 23)
%b = Abbreviated Month (i.e JAN, FEB, DEC)
%y = 2 digit year code (i.e 18, 80, 99)
Read more about formatting At this handy W3 Schools page
And use this DBFiddle for reference
To follow your desired format, use below;
select STR_TO_DATE('17-Dec-80', '%d-%b-%y');
To get last day of the month
select LAST_DAY(STR_TO_DATE('17-Dec-80', '%d-%b-%y'));
I want to find the number of days between today and selected date.
I used one query
SELECT DATEDIFF(CURDATE(), TILLDATE) FROM interestpr_table WHERE GLID="150";
But it returns NULL as result. How to fix?
As your TILLDATE is in format YYYY-MM-DD, you need to change it in YYYYMMDD format so that DATEDIFF would accept it as valid format.
SQLFIDDLE
For converting your date to format which DATEDIFF accept, you can use DATE_FORMAT like this :
SELECT DATEDIFF(curdate(),DATE_FORMAT(TILLDATE,'%Y%m%d')) // '%Y%m%d'converts it into YYYYMMDD format
SQLFIDDLE for conversion
I want to retrieve data between two specific date and I am getting that perfectly right with this query
select * from POS.dbo.voucher where date_time between '10 october 2014 00.00.00 ' and '11 october 2014 12.00.00'
but the issue is if I'm changing the month something like
select * from POS.dbo.voucher where date_time between '10 march 2014 00.00.00 ' and '11 march 2014 12.00.00'
It's still returning me with the same records. Seems like its only comparing the date and returning me the records.
Any idea where i m doing it wrong?
I am taking date as varchar in database.
Thanks!!
You appear to be using SQL Server (based on the dbo). Use a standard date format for date constants:
select *
from POS.dbo.voucher
where date_time between '2014-10-10 00:00:00' and '2014-10-11 12:00:00'
However, for this to work, you need to store dates using proper date formats in the database. So, you should fix the data structure to store dates using the correct data type.
I agree you would be better off changing the field from varchar to datetime. If that's not an option then you should convert the varchar field in the query into a datetime as appropriate in MS SQL Server, probably through a function, perhaps through a cast. BTW, best to tag with actually db used, and maybe SQL too.
I have read various questions here on Stackoverflow about the use of FROM_UNIXTIME but none directly deal with what I am trying to do. I have one timestamp in a variable coming from php (that has been reformatted - e.g. 25 March 2014) to a function which uses a database query to determine if there are other entries in the database that have the same date (not time). I've run across various methods for formatting and comparing timestamp entries using MySql and ended up with the following but I understand that it isn't very efficient. Does anyone know of a better way to accomplish this?
FROM_UNIXTIME(sd.timestart, "%e %M %Y") = ?'
where the variable in my array for comparison is the date format listed above. This accomplishes what I want but, again, I don't think it is the most efficient way to get this done. Any advice and/or ideas will be much appreciated.
*EDIT*
My timestamp is stored as an integer so I'm trying to use:
$thissessiondate = strtotime($date->timestart, strtotime('today'));
and
$tomorrowdate = strtotime($date->timestart, strtotime('tomorrow'));
to do trim to midnight but get an error (strtotime() expects parameter 2 to be long) and when I move 'today' to the first argument position, I get a conversion to 11 pm instead of 0:00...? I'm making some progress but my very incomplete knowledge of both PHP and MySQL are holding me back.
If you can avoid it, don't wrap columns used in predicates in expressions.
Have your predicates on bare columns to make index range scans possible. You want the datatype conversion to happen over on the literal side of the predicate, wherever possible.
The STR_TO_DATE function is the most convenient for this.
Assuming the timestart column is DATE, DATETIME or TIMESTAMP (which it really should be, if it represents a point in time.)
WHERE sd.timestart >= STR_TO_DATE( ? , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( ? , "%e %M %Y") + INTERVAL 1 DAY
Effectively, what that's doing is taking the string passed in as the first argument to the STR_TO_DATE function, MySQL is going to convert that string to a DATETIME, based on the format specified as the second argument. And that effectively becomes a literal that MySQL can use to compare to the stored values in the column.
If there's an appropriate index available, MySQL will consider an index range scan operation to satisfy that predicate.
You'd need to pass in the same value twice, but that's not really a problem.
On the second line, we're just adding a day to the same value. So what MySQL is seeing is this:
WHERE sd.timestart >= STR_TO_DATE( '25 March 2014' , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY
In terms of performance, that's equivalent to:
WHERE sd.timestart >= '2014-03-15 00:00:00'
AND sd.timestart < '2014-03-16 00:00:00'
If you do it the other way around, and wrap timestart in a function, that's going to require MySQL to evaluate the function on every single row (or at least, on every row that isn't filtered out by another predicate first.)
IMPORANT NOTE
Be aware that MySQL interprets datetime values as being in the timezone of the MySQL connection, which defaults to the timezone setting of the MySQL server. MySQL is going to interpret datetime literals in the current setting of the timezone. For example, if MySQL timezone is set to +00:00, then datetime literals will be interpreted as UTC.
I assumed the format string matches the data being passed in, I don't use %e or %m. The %Y is a four digit year. (The list of format elements is in the MySQL documentation, under the DATE_FORMAT function.
Reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date
If your timestart column is INTEGER or other numeric datatype, representing a number of seconds or some other unit of time since the beginning of an era, you can use the same approach for performance benefits.
In the predicate, reference bare columns from the table, and do any conversions required on the literal side.
If you aren't using MySQL functions to do the conversion to "seconds since Jan 1, 1970 UTC" when rows are inserted (which is really what the TIMESTAMP datatype is doing internally), then I wouldn't recommend using MySQL functions to do the conversion in the query either.
If you're doing the conversion from date and time to an integer type "timestamp" in PHP, then I'd do the inverse conversion in PHP as well, and do the trimming to midnight and the adding of a day in PHP.
In that case, your MySQL query would be of the simple form:
WHERE sd.timestart >= ?
AND sd.timestart < ?
Where you would pass in the appropriate integer values, to compare to the INTEGER timestamp column.
Note that MySQL does provide a function for converting to "seconds since Jan 1 1970 UTC", so if timestart is seconds since Jan 1 1970 UTC, then something like this is valid:
WHERE sd.timestart >= UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y"))
AND sd.timestart < UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY)
BUT... again, be aware of timezone conversion issues; if the MySQL database has a different timezone setting than the web server. If you are going to store "integer", then I wouldn't muck that up with the conversion that MySQL does, which may not be exactly the same as the conversion functions the web server does.
If you store your date as an int timestamp, you can do this
round(sd.timestart/86400)=round(UNIX_TIMESTAMP(NOW())/86400)
This will get everything in your database that is from the same day.
For example:
SELECT id FROM uploads WHERE (approved=0 OR approved is NULL) AND round(uploads.date/86400)<=round(UNIX_TIMESTAMP(NOW())/86400) order by uploads.date DESC LIMIT 20
Will display all the uploads for today and the days before, without showing the future uploads. 86400 is the number of seconds in one day.
I have stored the dates as string in my database.I know it is not good,but project already has been half developed before i take over and where dates were stored as string,so i was continuing the same way.
Now i want to select dates from table where date is greater than a specific date.
I tried the following query
SELECT
*
FROM
dates
where
STR_TO_DATE(date, '%Y-%m-%d') > "2014-01-01"
but it is not returning only greater values.
Please help me to solve problem.
Demo
Your dates are not in YYYY-MM-DD format. Use the right format!
SELECT *
FROM dates
where STR_TO_DATE(date, '%m-%d-%Y') > date('2014-01-01')
If you are going to store dates as strings, then the best way is in the ISO format of YYYY-MM-DD.
You should read the documentation on str_to_date() (here).
Convert everything to date and it should be fine. Now you are comparing date and string.
What type has the date? I'd prefer a ' instead of " for strings in SQL. Let's assume that date is a VARCHAR or TEXT field (depending on which database you are using):
SELECT *
FROM dates
WHERE STR_TO_DATE(date, '%Y-%m-%d') > STR_TO_DATE('2014-01-01', '%Y-%m-%d')
If date is a real DATE
SELECT *
FROM dates
WHERE trim(date) > STR_TO_DATE('2014-01-01', '%Y-%m-%d')
Or you just convert it into a number format date_format(date,'%Y%m%d') > 20140101