When a user clicks on a link, new data with the following format is stored in a MySQL_DB table called tracking_table:
id url title clicktime
1 http://1.com title 1 2014-12-07 21:33:53
2 http://2.com title 2 2014-12-07 21:34:03
3 http://1.com title 1 2014-12-07 19:30:00
4 http://3.com title 3 2014-12-07 18:38:47
5 http://1.com title 1 2014-12-07 22:23:54
6 http://2.com title 2 2014-12-07 20:17:20
7 http://7.com title 7 2014-12-07 10:20:12
8 http://1.com title 1 2014-12-07 21:38:03
How could I display (in PHP) in descending order the top 5 titles that were clicked on over the past 6 hours? Given the data recorded so far (supposing that NOW is 2014-12-07 22.24.00), my result should look like:
# url no. of clicks title
1 http://1.com 4 title 1
2 http://2.com 2 title 2
3 http://3.com 1 title 3
I have created the DB using this command:
CREATE TABLE `tracking_table` (
id int(11) unsigned NOT NULL AUTO_INCREMENT,
url varchar(255) DEFAULT NULL,
title varchar(255) DEFAULT NULL,
clicktime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
Any help would be much appreciated!
You should group the clicks by url and title, count them and then use a limit clause to retrieve only the top 5:
SELECT url, title, COUNT(*)
FROM tracking_table
WHERE DATE_DIFF (NOW(), clicktime) * 24 <= 6
GROUP BY url, title
ORDER BY 3 DESC
LIMIT 5
I would suggest the following:
select tt.title, count(*)
from tracking_table tt
where clicktime >= date_sub(now(), interval - 6 hours)
group by title
order by count(*) desc
limit 5;
This is similar to Mueinik's answer, with one important exception: the where clause. First, this calculation should work and second clicktime is not an argument to a function. The latter means that an index on clicktime could be used. (There is not one in the table definition, but it might be a good idea for this type of query.)
Related
I am setting up a database which stores posts for a website called "news". Each news post can have some (0-255) media(s) stored with it. I can get all the data like so:
SELECT *
FROM news
LEFT JOIN media ON news.id = news_id
Which returns:
news.id
title
created
media.id
news_id
filename
1
Title1
...
NULL
NULL
NULL
2
Title2
...
NULL
NULL
NULL
3
Title3
...
NULL
NULL
NULL
4
Title4
...
NULL
NULL
NULL
5
Title5
...
1
5
media1.png
5
Title5
...
2
5
media2.png
Notice that news.id = 5 shows up for twice since it has two images associated with it.
My goal is to get the latest 3 posts like so
SELECT *
FROM news
LEFT JOIN media ON news.id = news_id
ORDER BY created DESC
LIMIT 3
Which returns:
news.id
title
created
media.id
news_id
filename
5
Title5
...
2
5
media2.png
5
Title5
...
1
5
media1.png
4
Title4
...
NULL
NULL
NULL
However I would like it to return all the posts with ids 5, 4, and 3 along with all their media like so:
news.id
title
created
media.id
news_id
filename
5
Title5
...
2
5
media2.png
5
Title5
...
1
5
media1.png
4
Title4
...
NULL
NULL
NULL
3
Title3
...
NULL
NULL
NULL
Is this possible with MySql or is there some other database organization that can accomplish this? Basically I would like to only limit the results from the LEFT table and let the "repeats" show up so I can still get all the RIGHT table data. I am using PHP prepared statements to make these MYSQL queries so I may not be able to use subquery but I am not sure.
Select from a subquery that gets the last 3 posts, rather than the whole table.
SELECT *
FROM (
SELECT *
FROM news
ORDER BY created DESC
LIMIT 3
) AS news
LEFT JOIN media ON news.id = news_id
i have 52k rows of records in my user table. In that table user_hash column having approximately 2000 duplicate values. i want to update user_hash columns 2nd duplicate value. The following table user_id (3, 10), (5, 14) having same value and i want to update user_id 10 and 14 values. how can i update it with MySQL Qry?
--------------------------------
user_id user_hash user_status
--------------------------------
1 ae57250b 1
2 310cb4e0 1
3 28b365c7 1
4 0073265b 1
5 8bec42a9 1
6 00a5c443 1
7 e1c27b19 1
8 993dc301 1
9 8fc8a6bf 1
10 28b365c7 1
11 194714c0 1
12 4611d83a 1
13 277a426b 1
14 8bec42a9 1
15 740c1412 1
... ... ...
... ... ...
... ... ...
The following qry which i have used to check duplicate entry
SELECT user_hash, COUNT(user_hash)
FROM user_data
GROUP BY user_hash
HAVING COUNT(user_hash) > 1;
The first thing that comes to mind is that you may want to define a constraint such that in the future you can't have non-unique values where you don't want them.
The second thing is to ensure that these hashes can't legitimately collide/overlap.
Those thoughts aside (as they may be irrelevant to your use case):
update user_data set user_data.user_hash = STORED_PROC_FOR_HASH()
from (
select *, row_number() over(partition by user_hash order by (select null)) row_num
from user_data
) user_data
where row_num > 1
Source for the above query: https://stackoverflow.com/a/25090251/3080207
As hinted at by Nick, you'll need to be able to generate a unique hash, which is pretty much the 2nd component to this problem.
Hopefully that is helpful.
I have one table named:
thread_comment
Now the table is getting filled as followed:
thread_comment_id thread_id user_id thread_comment thread_comment_time
1 2 1 This is a comment 2016-09-14 15:30:28
2 4 1 This is a comment 2016-09-14 15:32:28
3 2 1 This is a comment 2016-09-14 15:33:28
4 5 1 This is a comment 2016-09-14 15:34:28
5 7 1 This is a comment 2016-09-14 15:35:28
6 2 1 This is a comment 2016-09-14 15:37:28
7 2 1 This is a comment 2016-09-14 15:40:28
I want to show the newest threads to my page. for example:
as number one i want thread_comment_id 7
as number two i want thread_comment_id 5
I skipped 6 because i don't want any duplicates in the list.
In order to do so i did the folowing:
$sql = "SELECT DISTINCT thread_id FROM thread_comment ORDER BY thread_comment_time DESC"
This is kind of working (Not showing any duplicates). However the order does not make any sense...
For example:
It goes like 5 - 6 -4 - 7 etc...
The column used in the ORDER BY isn't specified in the DISTINCT. You need to use an aggregate function and GROUP BY to make the DISTINCT work.
SELECT DISTINCT thread_id, max(thread_comment_id) FROM thread_comment GROUP BY thread_id ORDER BY max(thread_comment_id) DESC, thread_id
EDIT: added aggregate func max()
Also thread_id is not mandatory in the ORDER BY
It I understand correctly, you want one row per thread. Here is a way to do this:
select tc.*
from thread_comment tc
where tc.thread_date = (select max(tc2.thread_date)
from thread_comment tc2
where tc2.thread_id = tc.thread_id
);
I have a table "article_likes" of users and whether they like or dislike the article. With every like/dislike the datetime is saved and the id of the article. The like/dislike is saved as a bool in the "status" column.
id article_id user_id like_date status
1 8 2 2014-11-03 21:30:33 1
2 8 2 2014-11-03 21:31:00 0
3 8 3 2014-11-03 22:30:59 1
4 9 6 2014-11-03 22:36:25 1
5 9 2 2014-11-03 23:19:46 1
I like to get the amount of likes an article has. So only the status of the most recent date is valid for the count.
So the desired result would be:
article_id amount_likes
8 1
9 2
I want to get the result per article id, so not all at once.
Can anybody help me? Thanks!
This will solve your problem :)
SELECT article_id, SUM(IF(status = 1, 1, -1)) AS amount_likes FROM article_likes
GROUP BY article_id
If you store dislikes as -1 then:
SELECT article_id, SUM(status) AS amount_likes FROM article_likes
GROUP BY article_id
Try this:
SELECT `article_id`,COUNT(`user_id`) AS amount_likes FROM `links`
WHERE `status`='1' GROUP BY DATE(`like_date`), `user_id`;
Fiddle here - http://sqlfiddle.com/#!2/3b7bb6/4
Hope it helps
SELECT article_id, COUNT(IF(
SELECT CASE
WHEN status=1 THEN 'true'
ELSE 'false'
END),
'true','false'
)
)
FROM article_likes
GROUP BY article_id
ORDER BY article_id
i am facing a very weird problem.
Basically i need to extract a set of rows from a table where every row is the "oldest" in its own group.
The table is structured as follow:
id, integer
domain_id, integer
value, integer
created_at, datetime
My query is
SELECT * FROM domains_urls GROUP BY domain_id HAVING created_at = MAX(created_at)
If i am not wrong, it should group the rows by domain_id and extract the one that it matches created_at = MAX(created_at).
The point is that it does not work as expected!
The table content is
id domain_id value created_at
1 2 1 2014-05-25 10:30:13
2 1 3 2014-05-25 19:30:13
3 2 2 2014-05-25 11:30:13
4 2 7 2014-05-25 15:30:13
5 2 4 2014-05-25 12:30:13
6 2 5 2014-05-25 13:30:13
I should get two rows:
id domain_id value created_at
2 1 3 2014-05-25 19:30:13
4 2 7 2014-05-25 15:30:13
Instead i get only
id domain_id value created_at
4 2 7 2014-05-25 15:30:13
I'm using MySQL 5.5 on Windows 7
I need to use an HAVING+GROUP BY or a DISTINCT+ORDER BY (not tested).
Thanks!
EDIT:
Because i am a dumb (i should avoid working on sunday), the value returned by MAX is related to the table and not to the group!
You can accomplish this by joining the table back to itself using the max(created_at):
select du.*
from domains_urls du
join (select domain_id, max(created_at) maxcreated_at
from domains_urls
group by domain_id
) du2 on du.domain_id = du2.domain_id
and du.created_at = du2.maxcreated_at
SQL Fiddle Demo
Try something like this
Select * from urls as u group by u.id having u.created >= any (select created from urls u2 where u.id == u2.id)
i have not tested this, just wrote that from the top of my head