选择每个用户收到的前N条消息

时间:2016-07-14 20:14:57

标签: mysql

我有一个表存储发送给用户的消息,布局如下

id (auto-incrementing) | message_id | user_id | datetime_sent

我正在尝试找到每个用户收到的第一个N message_id,但我完全被卡住了。我可以基于每个用户轻松完成(在查询中定义用户ID时),但不能用于所有用户。

注意事项:

  • 许多用户可以获得相同的message_id
  • 消息ID不是按顺序发送的(即我们可以在消息200之前发送消息400)
  • 这是一个只读的mySQL数据库

编辑:第二个想法我删除了这一点,但已将其添加回去了,因为有人善于处理它

最终目标是查看有多少用户打开了他们收到的前N条消息之一。

这个打开的表看起来像这样:

user_id | message_id | datetime_opened

2 个答案:

答案 0 :(得分:0)

这是对原始问题的未经测试的答案(前5个有2个表格和条件):

SELECT DISTINCT user_id
FROM   (   
            SELECT     om.user_id,
                       om.message_id,
                       count(DISTINCT sm2.message_id) messages_before
            FROM       opened_messages om
            INNER JOIN sent_messages sm
                   ON  om.user_id = sm.user_id
                  AND  om.message_id = sm.message_id
            LEFT JOIN  sent_messages sm2
                   ON  om.user_id = sm2.user_id
                  AND  sm2.datetime_sent < sm.datetime_sent
            GROUP BY   om.user_id,
                       om.message_id
            HAVING     messages_before < 5
        ) AS base

子查询加入sm2以计算发送给同一用户的先前消息的数量,然后having子句确保发送的消息少于5个。对于同一用户,可能有多条消息(最多5条)具有该条件,外部查询仅列出符合条件的唯一用户。

答案 1 :(得分:0)

要获取前N个(此处为2条)消息,请尝试

    var hunt = new RegExp(action.search);
    var aSelector = document.getElementsByTagName('a');
    var arr = Array.prototype.filter.call(aSelector, function(el){
        return hunt.test(el.href)
    });
    for(var i=0; i<arr.length; i++){
        var elem = arr[i].getAttribute('href');
        elem.onclick = function(){
            doStuff();
        };
    }

使用 RANK 替换,派生自@Seaux response mysql是否具有Oracle的“分析函数”?

要将其扩展到原始问题,只需添加适当的计算:

SELECT
  user_id
  , message_id
FROM (
  SELECT
    user_id
    , message_id
    , id
    , (CASE WHEN @user_id != user_id THEN @rank := 1 ELSE @rank := @rank + 1 END) AS rank,
      (CASE WHEN @user_id != user_id THEN @user_id := user_id ELSE @user_id END) AS _
  FROM (SELECT * FROM MessageSent ORDER BY user_id, id) T
  JOIN (SELECT @cnt := 0) c
  JOIN (SELECT @user_id := 0) u
) R
WHERE rank < 3
ORDER BY user_id, id
;

在MySQL中没有CTE,并且在只读数据库中 - 我认为在语句中没有两次使用上述查询。

查看实际操作:SQL Fiddle

请评论是否需要调整/进一步详细说明。