So I have a table contains log activity for users over the course of a certain period and looks as such:
message_table
+--------+------------+----------------------+
| Userid | Message_Id | Timestamp |
+--------+------------+----------------------+
| 3433 | 10051 | 05-Jun-2015 04:00:00 |
| 6321 | 10052 | 05-Jun-2015 04:01:00 |
| 83821 | 10053 | 05-Jun-2015 04:01:15 |
| ... | ... | ... |
| 2041 | 20052 | 15-Jun-2015 23:59:00 |
+--------+------------+----------------------+
I also have a list of users that I'm interested in doing activity counts.
interesting_userid
╔════════╗
║ Userid ║
╠════════╣
║ 3433 ║
║ 83821 ║
║ 1454 ║
╚════════╝
My goal: I want to pick a certain timeframe (let's say between Jun 7 and Jun 9 for example). I want to have a table that has for each day in the timeframe, all userid's, and then their respective counts.
This is the view I'm looking for:
+-----------+--------+--------------+
| DayOfWeek | Userid | num_messages |
+-----------+--------+--------------+
| Jun 7 | 3433 | 2 |
| Jun 7 | 83821 | 5 |
| Jun 7 | 1454 | 0 |
| Jun 8 | 3433 | 1 |
| Jun 8 | 83821 | 5 |
| Jun 8 | 1454 | 2 |
| Jun 9 | 3433 | 0 |
| Jun 9 | 83821 | 3 |
| Jun 9 | 1454 | 1 |
+-----------+--------+--------------+
Instead what I get - rows where counts() are 0 are being excluded:
+-----------+--------+--------------+
| DayOfWeek | Userid | num_messages |
+-----------+--------+--------------+
| Jun 7 | 3433 | 2 |
| Jun 7 | 83821 | 5 |
| Jun 8 | 3433 | 1 |
| Jun 8 | 83821 | 5 |
| Jun 8 | 1454 | 2 |
| Jun 9 | 83821 | 3 |
| Jun 9 | 1454 | 1 |
+-----------+--------+--------------+
query looks something like this:
select some_date_interval_function(me.timestamp) as DayOfWeek, iu.userid, count(me.message_id)
from interesting_userid iu
left join message_table me
on iu.userid = me.userid
where me.timestamp between '07-Jun-2015' and '09-Jun-2015'
group by DayOfWeek, iu.userid
You can test the query here: SQL Fiddle
WITH valid_date_range(valid_date) AS (
SELECT x.range_start + LEVEL - 1
FROM (SELECT TO_DATE('2015-06-07', 'YYYY-MM-DD') AS range_start,
TO_DATE('2015-06-09', 'YYYY-MM-DD') AS range_end
FROM dual) x
CONNECT BY x.range_start + LEVEL - 1 <= x.range_end),
message_count_by_user_and_date(message_date, userid, num_messages) AS (
SELECT d.valid_date, iu.userid, COUNT(me.message_id)
FROM interesting_userid iu
JOIN valid_date_range d ON 1 = 1
LEFT JOIN message_table me
ON me.userid = iu.userid
AND me.timestamp >= d.valid_date
AND me.timestamp < d.valid_date + 1
GROUP BY d.valid_date, iu.userid)
SELECT some_date_interval_function(m.message_date) AS DayOfWeek,
m.userid,
m.num_messages
FROM message_count_by_user_and_date m
ORDER BY m.message_date, m.userid;
You can try this:
select u.userid, DayOfWeek, tot_messages
from selected_users u
left join ( select userid,
some_date_interval_function(me.timestamp) as DayOfWeek,
count(*) tot_messages
from messages where tstamp between '07-Jun-2015' and '09-Jun-2015'
group by userid) e
on u.userid=e.userid;
change the tables and columns to yours and add the required columns to the final select.
The simplest method is to move the condition from the where
clause to the on
clause:
select some_date_interval_function(me.timestamp) as DayOfWeek, iu.userid,
count(me.message_id)
from interesting_userid iu left join
message_table me
on iu.userid = me.userid and
me.timestamp between '07-Jun-2015' and '09-Jun-2015'
group by DayOfWeek, iu.userid;
Your from
clause is turning the left join
into an inner join
.
I would suggest that you write the dates using ANSI standard format:
from interesting_userid iu left join
message_table me
on iu.userid = me.userid and
me.timestamp between date '2015-06-07' and '2015-06-07'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.