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
Related
I want to get the today count of users and yesterday's users count for that i want to write only one query how can i do that..?
these are my queries I want only one query:
SELECT COUNT(*) FROM visitors group by visited_date ORDER by visited_date DESC limit 1,1 as todayCount
SELECT COUNT(*) FROM visitors group by visited_date ORDER by visited_date DESC limit 1,0 as yesterdayCount
My expected results or only 2 columns
todayCount yesterdayCount
2 4
This should do the trick:
SELECT COUNT(CASE
WHEN visited_date = CURDATE() THEN 1
END) AS todayCount ,
COUNT(CASE
WHEN visited_date = CURDATE() - INTERVAL 1 DAY THEN 1
END) AS yesterdayCount
FROM visitors
WHERE visited_date IN (CURDATE(), CURDATE() - INTERVAL 1 DAY)
GROUP BY visited_date
ORDER by visited_date
If you know the current and previous date, then you can do:
SELECT SUM(visited_date = CURDATE()) as today,
SUM(visited_date = CURDATE() - interval 1 day) as yesterday
FROM visitors
WHERE visited_date >= CURDATE() - interval 1 day;
If you don't know the two days, then you can do something similar, getting the latest date in the data:
SELECT SUM(v.visited_date = m.max_vd) as today,
SUM(v.visited_date < m.max_vd) as yesterday
FROM visitors v CROSS JOIN
(SELECT MAX(v2.visited_date) as max_vd FROM visitors v2) as m
WHERE v.visited_date >= m.max_vd - interval 1 day
Just try this simple query
select visited_date as date, COUNT(*) as count from `visitors`
group by `visited_date` order by `visited_date` asc
It will produce output as
It will work for you.
Try this:
$sqlToday = "Select COUNT(*) FROM menjava WHERE DATE(date_submitted)=CURRENT_DATE()";
$sqlYesterday = "Select COUNT(*) FROM menjava WHERE DATE(dc_created) = CURDATE() - INTERVAL 1 DAY";
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)
I am using below query:
$select_jan1 = "SELECT count(*) FROM users WHERE timeStamp BETWEEN '2015-01-01' and '2015-01-31'";
$select_feb1 = "SELECT count(*) FROM users WHERE timeStamp BETWEEN '2015-02-01' and '2015-02-28'";
$select_mar1 = "SELECT count(*) FROM users WHERE timeStamp BETWEEN '2015-03-01' and '2015-03-31'";
Is there way to put this 3 query in one ?
Thank You
You can put the values in three columns, using conditional aggregation:
SELECT SUM(timeStamp BETWEEN '2015-01-01' and '2015-01-31') as cnt_201501,
SUM(timeStamp BETWEEN '2015-02-01' and '2015-02-28') as cnt_201502,
SUM(timeStamp BETWEEN '2015-03-01' and '2015-03-31') as cnt_201503
FROM users;
Do note that this logic ignores that values on the last day of each month. Better logic is:
SELECT SUM(timeStamp >= '2015-01-01' and timestamp < '2015-02-01') as cnt_201501,
SUM(timeStamp >= '2015-02-01' and timestamp < '2015-03-01') as cnt_201502,
SUM(timeStamp >= '2015-03-01' and timestamp < '2015-04-01') as cnt_201503
FROM users
WHERE timeStamp >= '2015-01-01' and timeStamp < '2015-04-01';
With whole months, I do so:
SELECT
count(*)
FROM
(SELECT
year(timestamp) AS year_, month(timestamp) AS month_
FROM
users) s
WHERE
s.year_ = 2015 AND s.month_ >=4
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`
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?