Using 'DATE_SUB(now(), INTERVAL 2 MONTH)' properly with Codeigniter - php

I'm trying to run this query with Codeigniter:
SELECT * FROM `bf_bs_history` WHERE date > DATE_SUB(now(), INTERVAL 2 MONTH)
If I enter it directly in phpMyAdmin, I get the result I want. However, running if from the code, it will not take any effect. It's not filtering at all.
The PHP line looks like this:
$this->history_model->where(array('date > ' => 'DATE_SUB(now(), INTERVAL 2 MONTH)'))->find_all();
Any idea where I go wrong?

CodeIgniter Active Record is adding backticks to your statement, which renders your clause as a string, not an executable function. You can set a second parameter to false to stop that. Also, for a function predicate like this you can simply pass in the string:
$this->history_model->where("date > DATE_SUB(now(), INTERVAL 2 MONTH)", false)->find_all();

Related

mySQL Workbench Error: Syntax Error, unexpected single quotes

I was trying to make a SQL statement in PHP, to convert a string into a time(6). But I have tried everything, for the last 12 hours, and have not made an inch of progress. I have tried these statements, all yield the same error.
UPDATE scheduling SET start='03:42PM' WHERE activityid=2;
UPDATE scheduling SET start=CONVERT(TIME(6),'03:42PM');
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'03:42PM'));
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'03:42PM'));
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'15:42'));
The error is
Syntax Error: unexpected '03:42PM'(single quoted text)"
I do not know how to fix this, the table exists, and i have sucesfully got other info using statements like SELECT activityid=2 FROM xxxxxx.scheudling
I guess I have two questions, either answer would work.
In my PHP document, how would I convert a string I get in from an Android Studio volley to a date. (I get the variable correctly, with $start=$_Post("start"), so that works, but I cant convert it into a time. I looked online, and tried everything that looked like it work work.
Conversion through SQL Code, I already tried CAST and CONVERT, neither works. My start column is type TIME(6).
I recommend testing expressions using a SELECT statement.
Firstly, the MySQL CONVERT function arguments are flipped around backwards.
The syntax is CONVERT(expr,type)
And type is supplied as a keyword, not a string literal. For example:
SELECT CONVERT('235',SIGNED)
To convert to a TIME datatype
SELECT CONVERT( '15:42' ,TIME(6)) // => 15:42:00.000000
The 'PM' part of the string literal will be ignored.
SELECT CONVERT( '03:42PM' ,TIME(6)) // => 03:42:00.000000
We can use the STR_TO_DATE function to return a TIME value from a string that contains the AM/PM indicator
SELECT STR_TO_DATE( '03:42PM' ,'%h:%i%p')
And there's no need to cast that to TIME(6), we can do this:
UPDATE scheduling
SET start = STR_TO_DATE( '03:42PM' ,'%h:%i%p')
WHERE activityid = 2
The STR_TO_DATE function is documented here:
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date
The format patterns for STR_TO_DATE are documented here, under DATE_FORMAT:
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format
FOLLOWUP
Demonstration:
setup
USE test;
CREATE TABLE scheduling (activityid INT PRIMARY KEY, start TIME(6));
-- 0 row(s) affected
INSERT INTO scheduling (activityid) VALUES (2);
-- 1 row(s) affected
execute the update statement in the answer above
UPDATE scheduling SET start = STR_TO_DATE( '03:42PM' ,'%h:%i%p') WHERE activityid = 2 ;
-- 1 row(s) affected
results
SELECT * FROM scheduling WHERE activityid = 2;
-- activityid start
-- ---------- ---------------
-- 2 15:42:00.000000
SECOND FOLLOWUP
Use same sql_mode setting reported by OP:
SET ##sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' ;
Test:
SELECT STR_TO_DATE( '03:42PM' ,'%h:%i%p')
returns
(NULL)
But this more complicated expression:
SELECT TIME(STR_TO_DATE(CONCAT(CURRENT_DATE(),' ', '03:42PM' ),'%Y-%m-%d %h:%i%p'))
returns
15:42:00
The more complicated expression is a workaround to avoid behavior imposed by the STRICT_TRANS_TABLES and NO_ZERO_DATE in the sql_mode.

ZF2 mysql query with interval

In my application I want to print a list with members who where online the last 5 minutes.
I tried to create this by mysql interval with the code below;
$interval = 5;
$select->where(array('member_last_online > ?' => 'SUBDATE(NOW(), INTERVAL '.$interval.' MINUTE)'));
Which produce this notice;
Notice: Attempting to quote a value without specific driver level support can introduce security vulnerabilities in a production environment. in ..zf_path..
The output from 'getSqlSTring()' is;
SELECT "members".* FROM "members" WHERE member_last_online > 'SUBDATE(NOW(), INTERVAL 5 MINUTE)'
If I execute the query below directly on the table it returns the data as accepted:
SELECT members.* FROM members WHERE member_last_online > SUBDATE(NOW(), INTERVAL 5 MINUTE)
What am I do wrong here?
You need to pass the db platform to getSqlString() to avoid the warning (so it knows how to quote values):
// assuming $db is the DB adapter instance
echo $select->getSqlString($db->getPlatform());
the solution to your main question is:
$select->where(new \Zend\Db\Sql\Predicate\Expression('SUBDATE(NOW(), INTERVAL '.$interval.' MINUTE)'));
or more readably:
use Zend\Db\Sql\Predicate\Expression;
$select->where(new Expression('SUBDATE(NOW(), INTERVAL '.$interval.' MINUTE)'));

MySQL query with date ranges returning no results

So I am doing this query from PHP, and here listerally the exact query string:
SELECT * FROM `pdem_timesheet`.`tblMasterTimesheets` WHERE
`pdem_timesheet`.`tblMasterTimesheets`.`username` = 'pdem' AND
`pdem_timesheet`.`tblMasterTimesheets`.`date` >= '2012-05-09' AND
`pdem_timesheet`.`tblMasterTimesheets`.`date` <= '2012-05-15' ORDER BY
`pdem_timesheet`.`tblMasterTimesheets`.`date` ASC
It looks like it should be correct to me (more-or-less copying it from previous code I used that DOES work). But when I run the query, the results are empty.
If I change the query to not be a date range, but just a single day:
SELECT * FROM .... WHERE ...`date` = '2012-06-12' ....
it works just fine, returns the one result that it should.
I have tried using the between keyword:
SELECT * FROM ... WHERE ...`date` BETWEEN [start] [end]
but it still returns nothing...
Any ideas how to get this query to return a result?
===ANSWER===
When you go:
var curr_date = now.getDate();
var curr_month = now.getMonth();
var curr_year = now.getFullYear();
it returns the month - 1 for some reason. So if now's month is 6, now.getMonth() will return 5...Just need to add 1 in the query (wish I saw this sooner)
Your query seems to be working for me.
See demo.
Query I have is
SELECT * FROM tblMasterTimesheets
WHERE
username='pdem'
AND
date >= '2012-05-09' AND
date <= '2012-05-15'
ORDER BY date ASC
I assume, username is of type varchar and date is of type timestamp or datetime.
Similar to Fahim Parkar, here is an example of your query working with the use of the BETWEEN syntax: http://sqlfiddle.com/#!2/0fcb5/4
It sounds like your user pdem does not exist.
Make sure that:
There is in fact a result which should be returned when using your
given criteria. Make sure the DD-MM-YYYY syntax is correct and make sure you know which month is which number (may is 05, june is 06)
That the datatype of the column date is of a date
type, not a generic text/varchar type. You cannot compare varchar with >= like that (not the way you want, at least. Only works on date types)
As Fahim said, your code is correct. It must be something within the table which is causing your issues.

Doctrine 2 DQL - nest expressions and functions in the QueryBuilder

I have found DoctrineExtensions module that has implement some useful MySQL functions. But I think my problem is a general one. How would you pass another mysql expression as a parameter into a function?
If I had 2 columns updated_at which is a DATETIME and lifespan which is an INT and I wanted to query whether the lifetime of an entity had expired, I could do this;
WHERE 0 > TIMESTAMPDIFF(SECONDS, NOW(), e.updated_at + INTERVAL e.lifespan SECOND)
IN the QueryBuilder it's something like this.
$qb->andWhere('0 > TIMESTAMPDIFF(SECONDS, CURRENT_TIMESTAMP(), e.updated_at + INTERVAL e.lifespan SECOND)');
But the parser doesn't like + INTERVAL e.lifespan SECOND because it expects the Close Parenthesis instead of a plus sign.
I realized I can use the DateAdd class from the DoctrineExtensions module.
TIMESTAMPDIFF(SECOND, CURRENT_TIMESTAMP(), DATEADD(e.updated_at, INTERVAL e.lifespan SECOND))

My Sql DATE_SUB() and codeigniter Active records issue?

i am using codeigniter active records to execute a simple mysql query to select data in last one hour.
so my query is:
SELECT * FROM tablename WHERE added_datetime >= DATE_SUB(NOW(),INTERVAL 1 HOUR)
and my codeigniter code to form this query is:
$data=array(
'added_datetime >='=>'DATE_SUB(NOW(),INTERVAL 1 HOUR)',
);
$query=$this->db->get_where('tablename',$data);
now the issue is codeigniter adds a single quotes around the DATE_SUB function and due to this the query not works on mysql server.
codeigniter produces:
SELECT * FROM (`tablename`) WHERE `added_datetime` >= 'DATE_SUB(NOW(),INTERVAL 1 HOUR)'
i also tried by adding FALSE as 3rd parameter in get_where but stil not worked
$query=$this->db->get_where('tablename',$data,FALSE);
it also produced the same query as above.
So please suggest me how to solve this issue.
-Thanks
Try doing something like this instead:
$this->db->where("added_datetime >= DATE_SUB(NOW(),INTERVAL 1 HOUR)", NULL, FALSE);
$query = $this->db->get('tablename');
$this->db->get_where(); doesn't provide the function to unescaping your where clause.

Categories