how would i create a "last 24 hour top" table by pageviews if i have the following tables.
movie: id, title
pageview: id, movie, vieweddate
i need the third table like this
top: id, movie, moviecount24
so i would be able to make such query:
select * from top24 order by viewcount24 desc limit 30
i need to create top table using ONE mysql query.
select
pageview.id as pageview_id
,movie.title as move_title
,count(movie.id) as moviecount24
from pageview
inner join movie on (pageview.movie = movie.id)
where pageview.vieweddate between date_sub(now(), interval 1 day) and now()
order by moviecount24 desc
limit 30;
Let me refactor Johan's response a bit:
INSERT INTO top
SELECT movie.id AS id, COUNT(movie.id) as moviecount24
FROM pageview
LEFT JOIN movie ON pageview.movie = movie.id
WHERE vieweddate > NOW() - INTERVAL 1 DAY
LEFT JOIN is important here, since some movies may have zero views, but still should be present in the result.
Related
I have two tables
clicks 2.ride
clicks Table
id | time
ride Table
id | timestamp
I want to get data from both tables group by GROUP BY EXTRACT(DAY FROM ride.timestamp)
but I am only getting data if I have entries in both tables for same day but I want data regardless if either table does not have data. I dont know if OUTER join is a answer but mysql does not support OUTER JOIN
My current query which only get data when I have entry present in both tables
COUNT(distinct ride.id) AS ride_ads,
COUNT(distinct clicks.id) AS clicks
FROM ride INNER JOIN clicks ON EXTRACT(DAY FROM ride.timestamp)=EXTRACT(DAY FROM clicks.time)
GROUP BY EXTRACT(DAY FROM ride.timestamp), EXTRACT(DAY FROM clicks.time)```
SELECT
DATE(ride.timestamp) AS Day,
COUNT(DISTINCT ride.id) AS ride_ads,
COUNT(DISTINCT clicks.id) AS clicks
FROM
ride
LEFT JOIN
clicks ON DATE(ride.timestamp) = DATE(clicks.time)
WHERE
DATE(ride.timestamp) > NOW() - INTERVAL 15 DAY
GROUP BY Day
UNION SELECT
DATE(clicks.time) AS Day, #selecting date from second table since I might have record in this table and I am using group by Day
COUNT(DISTINCT ride.id) AS ride_ads,
COUNT(DISTINCT clicks.id) AS clicks
FROM
ride
RIGHT JOIN
clicks ON DATE(ride.timestamp) = DATE(clicks.time)
WHERE
DATE(clicks.time) > NOW() - INTERVAL 15 DAY
GROUP BY Day
ORDER BY Day
I am trying to query users who has been active in the last 3 years.
I am adjusting a query I have used for years that I know works fine. The only part of the query that I am trying to add on is the part below that is outside the grey code. I can't get this part correct.
The column that I am querying the date for (lastactivity) is stored in int(10) format and I don't think I will be changing it because it is a VBulletin column and I don't want that change to affect so many other queries.
$query = "SELECT user.userid AS id3, user.lastactivity AS lastactivity1, DATE_FORMAT(FROM_UNIXTIME(user.lastactivity), '%Y %m %d') AS 'lastactivity2', socialgroup.groupid AS id1, socialgroupicon.groupid AS id2, socialgroupicon.dateline AS picdate, name, zip1, city1, state1, socialgroup.dateline AS groupdate, creatoruserid, members, picturecount, visible, paid
FROM socialgroup
LEFT JOIN socialgroupicon
ON socialgroupicon.groupid=socialgroup.groupid
LEFT JOIN user
ON user.userid=socialgroup.creatoruserid
WHERE type != 'inviteonly' AND state1 = '$region' AND lastactivity2 < UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL 3 YEAR))
ORDER BY paid DESC, lastactivity2 DESC, id1 ASC
LIMIT 100
";
if you are trying to get entries that were active within the last 3 years, your comparison should be a greater than:
lastactivity2 > UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL 3 YEAR))
Time moves forward, newer times are a bigger number than older times.
What you probably thought was that you wanted to compare 3 years to the time interval between today and the last activity, but you are comparing absolute timestamps, not differences.
The solution was that I need to change the LEFT JOIN on the user table to an INNER JOIN since the lastactivity column, which I am adding to there WHERE clause, is in that table. (I also need to change it to "lastactivity" instead of "lastactivity2).
$query = "SELECT user.userid AS id3, user.lastactivity AS lastactivity1, DATE_FORMAT(FROM_UNIXTIME(user.lastactivity), '%Y %m %d') AS 'lastactivity2', socialgroup.groupid AS id1, socialgroupicon.groupid AS id2, socialgroupicon.dateline AS picdate, name, zip1, city1, state1, socialgroup.dateline AS groupdate, creatoruserid, members, picturecount, visible, paid
FROM socialgroup
INNER JOIN user
ON user.userid=socialgroup.creatoruserid
LEFT JOIN socialgroupicon
ON socialgroupicon.groupid=socialgroup.groupid
WHERE type != 'inviteonly' AND state1 = '$region' AND lastactivity > UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL 3 YEAR))
ORDER BY paid DESC, lastactivity2 DESC, id1 ASC
LIMIT 100
";
I've got a database with events and organizations that run those events. I am looking to create a query that shows any organization that has not created an event in 90 days or more.
So far, I have this query:
SELECT organizations.name, organizations.first_name, organizations.last_name,
organizations.email, events.created_at, events.start_date, events.end_date
FROM events
INNER JOIN organizations ON events.organizer_id = organizations.id
WHERE DATE_SUB(CURDATE(),INTERVAL 90 DAY) > events.created_at
GROUP BY events.organizer_id
ORDER BY events.created_at DESC
The problem is that this will just choose any event that is more than 90 days old, but not the latest event. How do I get the query to look at the event with the newest created_at and see if that is 90 days or older and include only that?
You can use aggregation. If you care about organizations, then you don't need event information in the select:
SELECT o.name, o.first_name, o.last_name, o.email
FROM events e INNER JOIN
organizations o
ON e.organizer_id = o.id
GROUP BY o.id
HAVING DATE_SUB(CURDATE(), INTERVAL 90 DAY) > MAX(e.created_at)
ORDER BY MAX(e.created_at) DESC;
This query will not select organizations that never have events. To do that, you need a left outer join. Here is one way:
SELECT o.name, o.first_name, o.last_name, o.email
FROM organizations o LEFT JOIN
events e
ON e.organizer_id = o.id AND
e.created_at >= DATE_SUB(CURDATE(), INTERVAL 90 DAY)
WHERE e.organizer_id is null
GROUP BY o.id
ORDER BY MAX(e.created_at) DESC;
Note that I also changed the query to use table aliases. These make the query easier to write and read.
Try this:
First create a query (call it "A" here) that selects all organiazations which created an event in the last 90 days.
SELECT organizer_id from events where DATE_SUB(CURDATE(),INTERVAL 90 DAY) <= events.created_at
Then write a query which lists all organizations which are not in the result set of query A:
SELECT * from organizations where id not in (A)
Which makes it to:
SELECT * from organizations where id not in (SELECT organizer_id from events where DATE_SUB(CURDATE(),INTERVAL 90 DAY) <= events.created_at)
This works because SQL is "orthogonal", i.e., you can embed queries into other queries.
I'm in need of a better way of retrieving top 10 distinct UID from some tables I have.
The setup:
Table user_view_tracker
Contains pairs of {user id (uid), timestamp (ts)}
Is growing every day (today it's 41k entries)
My goal:
To produce a top 10 of most viewed user id's in the table user_view_tracker
My current code is working, but killing the database slowly:
select
distinct uvt.uid as UID,
(select count(*) from user_view_tracker temp where temp.uid=uvt.uid and temp.ts>date_sub(now(),interval 1 month)) as CLICK
from user_view_tracker uvt
order by CLICK
limit 10
It's quite obvious that a different data structure would help. But I can't do that as of now.
First of all, delete that subquery, this should be enough ;)
select
uvt.uid as UID
,count(*) as CLICK
from
user_view_tracker uvt
where
uvt.ts > date_sub(now(),interval 1 month)
group by
uvt.uid
order by CLICK DESC
limit 10
Try:
select uid, count(*) as num_stamps
from user_view_tracker
where ts > date_sub(now(), interval 1 month)
group by uid
order by 2 desc limit 10
I kept your criteria as far as getting the count for just the past month. You can remove that line if you want to count all.
The removal of DISTINCT should improve performance. It is not necessary if you aggregate in your outer query and group by uid, as that will aggregate the data to one row per uid with the count.
You should use Aggregate functions in MySQL
SELECT UID, COUNT(ts) as Number_Of_Views FROM user_view_tracker
GROUP BY UID
ORDER BY Number_Of_Views DESC
LIMIT 10
A simple demo which selects the top 10 UID viewed
http://sqlfiddle.com/#!2/907c10/3
I have a mysql database with vehicles records. I need a fast query that will return the newest records of those records that were updated within the last 4 minutes. For example vehicle "A" may be updated several times a minute so it will appear many times within the last 4min. Same with vehicle B C etc. I need only the most recent entries for each vehicle within a 4 min window. I have tried like this
SELECT *
FROM yourtable AS a
WHERE a.ts =
(SELECT MAX(ts)
FROM yourtable AS b
WHERE b.ts > NOW() - INTERVAL 5 MINUTE
AND b.name = a.name)
but it takes too long to produce results >10seconds.
You don't need the self-join.
select max(ts), name from Table1
where ts > NOW() - INTERVAL 5 MINUTE
group by name
To get all the rows for the latest updates and not only the name and timestamp:
SELECT t.*
FROM
TableX AS t
JOIN
( SELECT name
, MAX(ts) AS maxts
FROM TableX
WHERE ts > NOW() - INTERVAL 4 MINUTE
GROUP BY name
) AS grp
ON grp.name = t.name
AND grp.maxts = t.ts
You'll need at least an index on the timestamp column for this query.