Database query needs a lot of time - php

I am currently running this query and it takes around 15 sec to load i want to optimize the query
SELECT *, `points`.`players` as `players` ,
FROM_UNIXTIME(`points`.`timestamp`, '%Y-%m-%d %H:%i') as `date`,
(SELECT `points`.`players`
FROM `points`
WHERE FROM_UNIXTIME(`points`.`timestamp`, '%Y-%m-%d %H:%i') > `date` - INTERVAL 7 DAY
AND FROM_UNIXTIME(`points`.`timestamp`, '%Y-%m-%d %H:%i') < `date` - INTERVAL 167 HOUR
AND `server_id` = {$server_id}
AND `type` = 2
LIMIT 1
) as `prevplayers`
FROM `points`
WHERE `points`.`timestamp` > UNIX_TIMESTAMP(NOW() - INTERVAL 7 DAY)
AND `server_id` = {$server_id}
AND `type`=2
GROUP BY DATE_FORMAT(FROM_UNIXTIME(`points`.`timestamp`), '%Y-%m-%d %H')
ORDER BY DATE_FORMAT(FROM_UNIXTIME(`points`.`timestamp`),'%Y-%m-%d %H')
Table structure
Indexes
With Explain Output
Ideal time is 1-2 secs
Any Suggestions?
Thanks
Somdeb

Can you create an additional index with the columns in following order and retry the query?
server_id
type
timestamp (mention descending order)

Related

i have my value as 2018-05-03 11:02:00 in mysql i want to pass this in my where condition using php

In my table 'time' data is present on 2018-05-03 11:02:00 this datetime. So I want to get the data by passing this datetime.
Here is my code:
$query1=$this->db->query("SELECT sum(count) As total, sum(status) As
is_completed FROM `tasks` WHERE `staff_id` = '$datas[$i]' AND `time` >
DATE_SUB(CURDATE(), INTERVAL 1 HOUR)");
This code showing no results but there is a data present on this datetime. how
can i pass this datetime as where condition
CURDATE() returns a date only. So when you do DATE_SUB(CURDATE(), INTERVAL 1 HOUR), you are returning the equivalent of 23:00:00 Yesterday
It seems for what you are trying to do, it would be better to use NOW().
You can try the following query:
SELECT sum(count) AS total, sum(status) AS is_completed
FROM `tasks` WHERE `staff_id` = '$datas[$i]'
AND `time` > DATE_SUB(NOW(), INTERVAL 1 HOUR)
Change CUR_DATE() to NOW()
$query1=$this->db->query("SELECT sum(count) As total, sum(status) As is_completed FROM `tasks` WHERE `staff_id` = '$datas[$i]' AND `time` > DATE_SUB(NOW(), INTERVAL 1 HOUR)");

How to fill empty value when no record in that day using MySQL group by

SELECT `Date`, SUM(Clicks) AS Clicks, DAY(LAST_DAY(NOW())) AS Monthdays
FROM myTbl
WHERE ( DATE BETWEEN DATE_FORMAT(NOW(), '%Y-%m-01') AND NOW() )
AND MoverID = 123 GROUP BY `Date` ASC
I don't want use PROCEDURE like this: http://stackoverflow.com/questions/7252460/mysql-group-by-and-fill-empty-rows
I don't want to create a whole day containing table like this: http://stackoverflow.com/questions/5988179/mysql-group-by-date-how-to-return-results-when-no-rows
I can use SELECT ##global.time_zone, ##session.time_zone; in PHP and after the MySQL query result is out, I make PHP to the same timezone as MySQL, and fill the date by PHP. But is it a way I can just do it in MySQL way?
You can use a trick to generate virtual table having all the dates you need with another table (replace aux with any table in your DB with 31 recored at least):
SELECT CONVERT(#d := DATE_ADD(#d, INTERVAL 1 DAY), DATE) AS `d`
FROM
`aux`,
(SELECT #d := DATE_SUB(CONVERT(DATE_FORMAT(NOW(), '%Y-%m-01'), DATETIME), INTERVAL 1 DAY)) `x`
WHERE
#d < DATE_SUB(NOW(), INTERVAL 1 DAY)
LIMIT
31
And then join you table on it:
SELECT
`aux`.`d` as `Date`,
SUM(IFNULL(`Clicks`, 0))AS `Clicks`,
DAY(LAST_DAY(NOW())) AS `Monthdays`
FROM (
SELECT CONVERT(#d := DATE_ADD(#d, INTERVAL 1 DAY), DATE) AS `d`
FROM
`aux`,
(SELECT #d := DATE_SUB(CONVERT(DATE_FORMAT(NOW(), '%Y-%m-01'), DATETIME), INTERVAL 1 DAY)) `x`
WHERE
#d < DATE_SUB(NOW(), INTERVAL 1 DAY)
LIMIT
31
) aux
LEFT JOIN
myTbl
ON `Date` = `aux`.`d`
GROUP BY `aux`.`d`

Adjust mysql query to filter out today from the date

Hi all i currently have this sql:
SELECT a.*
FROM (SELECT a.*
FROM articles a
WHERE date >= UNIX_TIMESTAMP(DATE(NOW() - INTERVAL 7 DAY)) AND a.active = 1
ORDER BY views ASC
) a
ORDER BY views ASC
It lists all articles posted in the last week, what I want to do is adjust it so it ignored today, is that easy to do?
Certainly. You just need to add AND date < UNIX_TIMESTAMP(CURDATE())
For simplicity, you can use the BETWEEN operator:
WHERE `date` BETWEEN UNIX_TIMESTAMP(DATE(NOW() - INTERVAL 7 DAY))
AND UNIX_TIMESTAMP(DATE(NOW() - INTERVAL 1 DAY))
I believe this allows the engine to make better use of indexes than individual >= and <= calls, but I'm not certain on that.
Shouldn't
SELECT `a`.*
FROM `articles` AS a
WHERE `date` >= UNIX_TIMESTAMP(NOW(TODAY() - INTERVAL 7 DAY)) AND `date` <= UNIXTIMESTAMP(DATE(NOW() - INTERVAL 1 DAY)) `a`.`active` = 1
ORDER BY `views` ASC
Suffice for this task?

MySQL Query Date Errors

I have this query that indexes my images and orders them by popularity but I cant make the user to choose the interval cause there's something wrong with the query:
switch($Data['data']){
case 'daily':$QueryDate='=CURDATE()';break;
case 'weekly':$QueryDate=' BETWEEN SUBDATE(CURDATE(), INTERVAL 7 DAYS) AND NOW()';break;
case 'monthly':$QueryDate='>CURDATE() - INTERVAL 31 DAYS';break;
default: Core::redirect('image/browse/daily/1');break;
}
$IMGDB = new Database('images');
$query = "SELECT *, (derived.`likes` * 2 + derived.`views`) as `popularity` from
(SELECT *,
(SELECT COUNT(*) FROM `likes` WHERE `like`=I.id AND `date`".$QueryDate.") AS `likes`,
(SELECT SUM(`views`) FROM `views` WHERE `id`=I.id AND `date`".$QueryDate.") AS `views`
FROM images AS I
) AS derived
where 1 ORDER BY `popularity` DESC ";
Only the daily case works.
Here is the error:
SQL Error (1064): You have an error in your SQL syntax;..... to use near 'DAYS) AND NOW()) AS likes, (SELECT SUM(views) FROM views WHERE id= I.id A
The correct syntax for specifying an interval of days uses the DAY keyword. You've used DAYS in:
BETWEEN SUBDATE(CURDATE(), INTERVAL 7 DAYS) AND NOW()
and:
> CURDATE() - INTERVAL 31 DAYS

Selecting in between won't work with MySQL?

I have a quick and asap issue.
SELECT `deals`.*
FROM `deals`
WHERE
`is_featured` = 1 AND
`status` = 'active' AND
CURDATE() BETWEEN start_date AND DATE_ADD(end_date, INTERVAL 1 DAY)
ORDER BY `end_date` DESC
LIMIT 1
Is this right?
start_date is "2012-01-11 00:00:00" and end_date is "2012-01-11 23:59:59".
This is what I wish to show:
I want to show the dealoffer that is between the current datetime and if the is_featured is 1 and status are "active".
(CURDATE() gives me only date, not time, is this the problem? How can I get current datetime in MySql?).
It should only pick one deal and this deal should be the one with the closest end date from current datetime.
Here is your original query
SELECT `deals`.* FROM `deals`
WHERE `is_featured` = 1
AND `status` = 'active'
AND CURDATE() BETWEEN start_date AND DATE_ADD(end_date, INTERVAL 1 DAY)
ORDER BY `end_date` DESC
LIMIT 1;
Replace the BETWEEN with this
SELECT `deals`.* FROM `deals`
WHERE `is_featured` = 1
AND `status` = 'active'
AND start_date >= (CURDATE() + INTERVAL 0 SECOND)
AND start_date <= (end_date + INTERVAL 1 DAY)
ORDER BY `end_date` DESC
LIMIT 1;
and add this index
ALTER TABLE deals ADD INDEX (is_featured,status,start_date,end_date);
Use now() to get the date and time.
You could use the curtime() function to retrieve the current time.

Categories