Postgresql search for items older than a threshold - php

Seems like this should be a simple thing to do, but the date/time operations in postgresql are killing me. All I'm looking to do is search for items older than 10 minutes. Coding language is PHP.
Field event_time is: timestamp without time zone NOT NULL
$sql = "SELECT * FROM incidents WHERE
event_time < ( now() - interval '-{$threshold} minutes' )
AND submitted=0 ";
This query is returning all results instead of items older than 10 minutes. Do I need to type cast that event_time field somehow?

By using a negative threshold value, you have a double negative, so you are searching for everything less than ten minutes in the future (which would naturally return everything). Just use interval '{$threshold} minutes}'

Related

Request to find out the date in 2 days

How to write a sql query to find out that there are 2 days left before the current date.
In php, this can be done via:
$res['end_date'] - time () < 86400 * 3;
How can I do the same after 1 sql query, well or better, only 2 days, if less so that it does not work out, well, if it works out, it's okay.
UPD:
It is necessary to compose a sql query that will select only those records that have 2 days left before the end_date expires
The type is int for the field end_date and is stored via the time () function in php.
Can't compose a WHERE clause.
You can use the FROM_UNIXTIME function to convert it to a DateTime you can then use the NOW() plus 2 days to check if the date is under 2 days. You then have to check that the date is before the current time otherwise you'll get dates that have already gone.
SELECT
end_date
FROM
table
WHERE
FROM_UNIXTIME(end_date) <= NOW() + INTERVAL 2 DAY
AND
FROM_UNIXTIME(end_date) > NOW()
Assuming that you are storing an epoch timestamp (the number of seconds since January 1st, 1970), I would recommend:
select *
from mytable
where end_date >= unix_timestamp() and end_date < unix_timestamp() + 2 * 24 * 60 * 60
unix_timestamp() gives you the current epoch. You can use simple math to add two days to that.
The upside of this approach is that this does direct filtering against the store value, so this can take advantagae of an index on end_date - as opposed to converting the timestamp to a date, which requires converting the whole column before the filtering can happen. So this is much more efficient.
You can ajust the inequalities as you prefer. I used a half-open interval (inclusive on the lower bound and exclusive on the upper bound), which is a widely used approach.
I ended up doing this:
$time = time();
$params = $db->query("SELECT * FROM `params` WHERE (`end_date` - {$time}) < 86400 * 3");
And it worked.
I always do
select *
from mytable
where FROM_UNIXTIME(end_date) < NOW() + INTERVAL 2 DAY
This will get results where two days in the future is ahead of the end date ie, anything that will end within 2 days (or has already ended as I didn't add a check for that)
Edit: I see you can't use where
If you cannot use where clause
select FROM_UNIXTIME(end_date) - INTERVAL 2 DAY as end_date
from mytable
And then check in php if the result is before or after. This will show all results however

how to Increase mysql search speed?

I have table in MySQL which has columns
id(primary key) ,deviceid(varchar) ,date(varchar),time(varchar),value(varchar) parameter(varchar)
I made mistake by separating time and date fields in my DB columns and then with my business logic where with lot of repetitive code
A new record is inserted every minute in database every day. My major query is to fetch data between two dates for a given number of deviceids such that data only one value is selected per interval ( this interval is decide by user input for exampe if interval is 1 hour i need 1 value between interval 00-01 hrs,1 value in terval hrs 01-02 hrs and so on 1 value from 23-24(00) hours )
My query is taking almost a minute to get data for and display for 2-3 days of data . And shorter the interval gets more time it takes .
I am new to databases and only knows basic CRUD operation . I have designed tabled through php myadmin default options.
I read about the concept of indexing to improve search performance and i am confused on which columns should I apply indexing.
Also my value columun is currently varchar but values of value column are all floating numbers(temperature/humidity of a boiler room). Can changing its type from varchar to int increase my speed ?
here is more explanation
I am using my php to display report
my time is in string format and so is date
for example date is stored as '08.31.2020'
and time is stored '23.05' (hours,min)
let say I want data from '08.01.2020' to '08.20.2020' and interval of 1 hour =60 minutes
Here is my business logic and querys
$time1 ='00.00'
$time2 ='01.00' // here I have increased time by adding 60 minutes to $time1 .
while(fromDate <= toDate)
{
for(each device in array)
{
$query = "Select parameter,value,time,date from currentdata where deviceid='device[$i]' and date='fromDate' and (time > '$time1' and time <= '$time2' ) order by time limit 1 "
}
$time1=$time2; //change interval
$time2 =$time2 +60 minutes //
If(time1>=time2)
{
// increment From date by 1
}
}
No of devices are about 30 -35 .
Parameter is just a name which will be either Temperate of humidity
Any general advice ,suggestion ,criticism will be helpful.
Use appropriate datatypes in the table. Numeric quantities should not be put in VARCHAR; use INT, DECIMAL, or FLOAT, as needed. (Or variants on them.)
If your incoming data is not "clean", the read it into a VARCHAR and 'cleanse' it as you copy it into the SMALLINT UNSIGNED, etc, in the real table.
Also DATE must have the year first.
Use things like + INTERVAL 1 HOUR for simple date or time arithmetic.
Usually it is better not to split date and time for storage, but to split as needed on output.
On your other Question, I admonished you to do the SELECT with a JOIN, not a loop.
After addressing all those things, provide SHOW CREATE TABLE, the new query, etc. Then I will weigh in on the index.

How to filter MySQL dates?

I'm trying to do a SELECT * FROM but only items that are less than 30 days old. Here is my select code:
SELECT * FROM `{$table_name33}` WHERE `type`='wpst-requiredinfo' ORDER BY `foreignkey` ASC;
However, my problem is that I can't figure out how to add WHERE AND last_updated is less than 30 days.
I'm not exactly sure how to write the query, but the date is showing up like this: 1428412603 in the table column, it doesn't look much like a date to me. I don't know where to start.
Try this where clause:
WHERE `type`='wpst-requiredinfo' and
last_updated >= date_sub(now(), interval 30 day)
EDIT:
Your date seems to be in Unix time format.
WHERE `type`='wpst-requiredinfo' and
last_updated >= unixtime_timestamp() - 30*24*60*60
Note: this puts all the functions on the current time. In particular, it does not use FROM_UNIXTIME(last_updated). This ensures that an index can be used for this part of the query. The best index would be on (type, last_updated).

MySQL Between issue not working with Unix Time Stamps

I am currently storing dates as Unix Time Stamps in an INT(10) column in a mysql version 4.0.8 db (MyISAM engine).
I query these dates to extract records between a date range using the following SQL:
$sql = "SELECT `users`.`real_name`, `users`.`user_value`, `clients`.`client_name`, `clients`.`client_stars`, `timing`.`start_date`, `timing`.`end_date`, `projects`.`project_name`
from timing
LEFT JOIN users on (users.id = timing.user_id)
LEFT JOIN clients on (clients.id = timing.client_id)
LEFT JOIN projects on (projects.project_id = timing.project_id)
WHERE start_date BETWEEN :start_date AND :end_date";
I am using PDO, hence the params.
I am 100% sure the :start_date and :end_date vars are correct in all cases as I have checked these. Also start_date is not ambiguous and there are no warnings/notices regarding this query.
My problem is that I do not get the rows expected. If I ask for rows between Midnight 2013/11/14 and Midnight 2013/11/15, the expectation is ONLY results from the 14th. However, rows from the 15th are also passed - but not all of them.
I also just tested between 1384473600 and 1384473600 - which is between midnight today and midnight today (as in the same timestamp).
The rows returned should be 0, yet it has returned all rows from today (for instance the first row returned has a start_date value of 1384524193)!
Have I missed something about how the between operator works in mySQL? How can it return rows when the min and max are the same?
I have tested and tested, and nearly every time I make a query, rows are returned that are ABOVE the specified between ceiling.
What is going wrong?
BETWEEN is a notoriously bad way to match dates and timestamps, because it's inclusive of both ends of the range.
This may work better for you
WHERE start_date >= :start_date
AND start_date < :end_date + 86400
The magic number 86400 is the number of seconds in a day. This selects all start_date values between midnight on the :start_date parameter inclusive, and then excludes all values on or after midnight on the day after the :end date. If you were using actual timestamps, you could say + INTERVAL 1 DAY instead of + 86400.
Although I do not know why, when I reversed the logic it worked perfectly.
WHERE timing.start_date < :end_date
AND timing.start_date >= :start_date
This did not work however, and returned the same erroneous results.
WHERE start_date >= :start_date
AND start_date < :end_date
Can Anyone explain why?

How to delete rows based on date differences with MySQL?

I need to delete rows where a datetime field is over 2 weeks old.
This is what I have came up with
$duration = Date::WEEK * 2; // int(1209600)
$query = 'DELETE FROM properties
WHERE TIMEDIFF(' . date(DATE_ISO8601) . ', reserved_datetime) > ' . $duration;
I don't often write complicated queries (preferring to do stuff in PHP, where I'm more comfortable) but I'd like to know more about them, plus doing this sort of thing in PHP would be very inefficient and I am handling a large amount of rows.
Anyone know what I'm doing wrong? Cheers.
Update
I gave Wallyk's answer a shot, changing it slightly in phpMyAdmin to SELECT just so I could see what was going on.
This is what I used
SELECT *
FROM properties
WHERE date_sub( `reserved_datetime` , INTERVAL 2 week ) >0
LIMIT 0 , 30
The only problem however, is that it has returned rows where the reserved_datetime is 2010-02-28 10:45:59, definitely less than 2 weeks ago (from now).
I thought of checking MySQL's internal date. I have been using date(DATE_ISO8601) in my queries, because MySQL's NOW() wasn't exactly right (it just returned if interested 2010-02-28 20:09:19).
Is there a way to specify the current date in that query? Any other suggestions?
Many thanks
Another Update
Here is a screenshot from phpMyAdmin that may demonstrate anything better than my words can. Oh, and the reason it has returned 3 only is because all the others have blank values, i.e. 0000-00-00 00:00:00
wallyk's answer is not correct. Think about what you're doing - subtracting two weeks from almost any date will still be greater than zero (zero = 1/1/1970). I think you want something more like this:
DELETE FROM properties WHERE DATE_SUB(NOW(), INTERVAL 2 WEEK) > reserved_datetime
Use:
FROM PROPERTIES p
WHERE p.reserved_datetime <= DATE_SUB(NOW(), INTERVAL 2 WEEK)
Mind that because of using NOW(), the two week old date will include the time portion.
I don't have a mysql database so I can't say if it works for sure, but it does in postgresql:
DELETE FROM properties WHERE (NOW() - reserved_datetime < interval '2 weeks')
Try this instead:
$query = 'DELETE FROM properties
WHERE date_sub(reserved_datetime, interval 2 week) > 0';
This assumes that reserved_datetime is the field name in the table.
(Tested with MySQL 5.0.46-standard.)

Categories