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)'));
Related
Trying to pull client information from SQL server using PHP and count how many clients signed up last month based on the date they signed up. I want to use DATEPART and DATEADD to specify the parameters I want for grabbing last months information, but the server doesn't seem to recognize these parameters. Currently using MySQL 5.6.44.
I know statements like
SELECT CLIENT_EMAIL
FROM CLIENT_TABLE
AND DATE_CLIENT_ADDED > (CURRENT_DATE() - INTERVAL 30 DAY)
works, but this is very limiting
$con = mysqli_connect($Host, $User, $Password, $DB);
$getLastMonthEnrollments = "SELECT CLIENT_EMAIL FROM CLIENT_TABLE AND DATEPART(m, DATE_CLIENT_ADDED) = DATEPART(m, DATEADD(m, -1, getdate()))";
$tempQuery = mysqli_query($con, $getLastMonthEnrollments);
$LastMonthEnrollments = mysqli_num_rows($tempQuery);
I expect to get a number from counting the rows, but my result is null. When I attempt to run this within the server itself, I get
FUNCTION my_DB.DATEPART does not exist
Am I doing this wrong? I've read many documentations and questions on here and this seems to be the correct usage.
You are using SQL Server syntax from your Laravel code, yet the underlying database is MySQL. Here is your query, rewritten and also corrected:
SELECT CLIENT_EMAIL
FROM CLIENT_TABLE
WHERE MONTH(DATE_CLIENT_ADDED) = MONTH(CURDATE() - INTERVAL 1 MONTH);
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.
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();
I'm attempting to work with two sets of data from the same mySQL table in a PHP script. The idea is data is scraped from an API and into a database hourly. A second script then pulls the information out of the database and displays a rolling 6-hour delta.
I've run into a bit of a problem trying to create the delta from the two datasets. I need to run two mySQL queries to get the data I need (current and from 6 hours ago), but can't really think of a way to get the script to work without including the queries inside the loops that output each entry (These can run up to a couple of hundred times, and I don't think having that many mySQL queries running would be good?)
This is what I have so far:
//select the system table and pulls data acquired within the last hour.
$sql = "SELECT system, vp, vpthreshold, owner, time FROM SysData WHERE time > DATE_SUB(NOW(),INTERVAL 1 HOUR)";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
//Calculates contested percentage
$vpthreshold = $row["vpthreshold"];
$vp = $row["vp"];
$currentcontested = $vp/$vpthreshold*100;
//Catches potential divide by zeroes, echos system is stable.
if ($vp == 0.0){
echo $row["system"] . " " . "is Stable<br>";
}
//else output contested percentage with system name in readable format.
else{
echo $row["system"] . " " . "{$currentcontested}%" . "<br>";
}
}
}
There's a broadly identical statement that pulls and echos the second set of information underneath this. How can I get these two sets together so I can work with them? Very new to PHP and learning on the fly here.
You can look into nested queries. Something like the following:
SELECT (data_now.somevalue - data_prev.somevalue) as deltavalue FROM
(
(your first select statement) as data_now,
(your 6 hours ago select statement) as data_prev
);
This lets you select data from other select statements all in one go.
The 2 inner "select statements" you should replace with your respective queries. The results will be put temporarily into data_now and data_prev. You can then use these as normal tables in the outer select statement.
EDIT: To be more specific to what you want, here is an updated example:
SELECT (data_now.vp/data_now.vpthreshold - data_prev.vp/data_prev.vpthreshold) as deltavalue FROM
(
(SELECT system, vp, vpthreshold, owner, time FROM SysData WHERE time > DATE_SUB(NOW(),INTERVAL 1 HOUR)) as data_now,
(your 6 hours ago select statement) as data_prev
);
In your PHP code remember to reference the result as:
$row["deltavalue"]
or whatever you put after "as" in the outer SELECT.
I have a weird problem.
I'm running a query:
SELECT IMIE, NAZWISKO, PESEL2, ADD_DATE, CONVERT(varchar, ADD_DATE, 121) AS XDATA, ID_ZLECENIA_XXX, * FROM XXX_KONWERSJE_HISTORIA AS EKH1
INNER JOIN XXX_DANE_PACJENTA EDP1 ON EKH1.ID_ZLECENIA_XXX=EDP1.ORDER_ID_XXX
WHERE EKH1.ID_KONWERSJE = (
SELECT MIN(ID_KONWERSJE)
FROM XXX_KONWERSJE_HISTORIA AS EKH2
WHERE EKH1.ID_ZLECENIA_XXX = EKH2.ID_ZLECENIA_XXX
)
AND EDP1.RECNO = (
SELECT MAX(RECNO)
FROM XXX_DANE_PACJENTA EDP2
WHERE EDP2.ORDER_ID_XXX = EDP1.ORDER_ID_XXX
)
AND EKH1.ID_ZLECENIA_XXX LIKE '%140000393%'
AND ADD_DATE>'20140419' AND ADD_DATE<='20140621 23:59:59.999'
ORDER BY EKH1.ID_KONWERSJE, EKH1.ID_ZLECENIA_XXX DESC
And the query works ok if I use a date limit around 2 months (63 days - it gives me 1015 results). If I extend the date limit query simply fails (Query failed blabla).
This happens under windows 64 bit php (apache, Xamp).
When I run this query directly from MS SQL SERWER Management Studio everything works fine, no matter what date limit I choose.
What is going on? Is there a limit of some kind under apache/php? (There is no information like "query time excessed", only "query failed")
And the query works ok if I use a date limit around 2 months (63 days
- it gives me 1015 results). If I extend the date limit query simply fails (Query failed blabla). ...
What is going on? Is there a limit of
some kind under apache/php? (There is no information like "query time
excessed", only "query failed")
This could happen because selectivity of ADD_DATE>'20140419' AND ADD_DATE<='20140621 23:59:59.999' is medium/low (there are [too] many rows that satisfy this predicate) and SQL Server have to scan (yes, scan) XXX_KONWERSJE_HISTORIA to many times to check following predicate:
WHERE EKH1.ID_KONWERSJE = (
SELECT ...
FROM XXX_KONWERSJE_HISTORIA AS EKH2
WHERE EKH1.ID_ZLECENIA_XXX = EKH2.ID_ZLECENIA_XXX
)
How many times have to scan SQL Server XXX_KONWERSJE_HISTORIA table to verify this predicate ? You can look at the properties of Table Scan [XXX_KONWERSJE_HISTORIA] data access operator: 3917 times
What you can do for the beginning ? You should create the missing index (see that warning with green above the execution plan):
USE [OptimedMain]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[ERLAB_KONWERSJE_HISTORIA] ([ID_ZLECENIA_ERLAB])
INCLUDE ([ID_KONWERSJE])
GO
When I run this query directly from MS SQL SERWER Management Studio
everything works fine, no matter what date limit I choose.
SQL Server Management Studio has execution timeout set to 0 by default (no execution timeout).
Note: if this index will solve the problem then you should try (1) to create an index on ADD_DATE with all required (CREATE INDEX ... INCLUDE(...)) columns and (2) to create unique clustered indexes on these tables.
Try to set these php configurations in your php script via ini_set
ini_set('memory_limit', '512M');
ini_set('mssql.timeout', 60 * 20);
Not sure it will help you out.