简体   繁体   中英

Viewing counts for all users in an activity table by the day without losing users who have 0 counts

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM