MySQL:选择所有USERS打开2条消息并在时间戳

时间:2016-05-16 19:05:03

标签: php mysql

我正在用PHP执行MySQL脚本。 所以我有3张桌子。

包含至少3 000 000行的邮件 (userid,messageid,timestamp,received,opened,clicked,deliveryid)

用户 (用户(唯一),个人资料,profile_actual_timestamp,last_delivery_id_sent)

events_clicked_data包含至少2 000 000行和详细点击事件。此用户在此消息(deliveryId)上单击此配置文件(如GAMES) (userid,profile,deliveryId,eventDate)

所以这里是消息和用户表的示例数据。

CREATE TABLE messages
    (`user_id` varchar(100), `message_id` int, `timestamp` datetime, `received` varchar(5), `opened` varchar(5), `clicked` varchar(5), `delivery_id` int);

INSERT INTO messages
    (`user_id`, `message_id`, `timestamp`, `received`, `opened`, `clicked`, `delivery_id`)
VALUES
    ("BillyStuff", 12,'2016-05-16 00:00:00', 'true', 'true', 'true', 8),
    ("BillyStuff", 11,'2016-05-14 00:00:00', 'true', 'true', 'true' , 7),
    ("BillyStuff", 8,'2016-04-03 00:00:00', 'true', 'false', 'false' , 6),
    ("BillyStuff", 4,'2016-04-02 00:00:00', 'true', 'false', 'false', 5),
    ("JohnDoe", 15 ,'2016-05-16 00:00:00', 'true', 'true', 'false' , 4),
    ("JohnDoe", 13 ,'2016-05-14 00:00:00', 'true', 'true', 'true', 3),
    ("Donnie", 15 ,'2016-05-16 00:00:00', 'true', 'true', 'true' , 4),
    ("Donnie", 13 ,'2016-05-14 00:00:00', 'true', 'true', 'true', 3)

CREATE TABLE users
    (`user_id` varchar(100), `profile` varchar(100), `profile_actual_timestamp` datetime, `last_delivery_id_sent` int);

INSERT INTO users
    (`user_id`, `profile`, `profile_actual_timestamp`, `last_delivery_id_sent`)
VALUES
    ("BillyStuff", "Game", "2016-01-01 00:00:00", 1),
    ("JohnDoe", "Book", "2016-01-01 00:00:00", 1),
    ("Donnie", "Book", "2016-05-16 00:00:00", 4)

我想让用户在个人资料中点击时间戳(profile_actual_timestamp表示上次更新后)后点击2条消息。

在这种情况下,我只获得BillyStuff,因为如果我检查profile_actual_timestamp,Donnie已经是最新的。

在此之后,如果点击了相同的类别,我需要在events_clicked表中按deliveryId和用户进行检查。

CREATE TABLE events_clicked_data
    (`user_id` varchar(100), `profile` varchar(100), `deliveryId` int, `eventDate` datetime);

INSERT INTO users
    (`user_id`, `profile`, `deliveryId`, `eventDate`) VALUES
    ("BillyStuff", "Book", 8,"2016-01-01 00:00:00"),
    ("BillyStuff", "Book", 7,"2016-01-01 00:00:00"),
    ("JohnDoe", "Book", 3,"2016-01-01 00:00:00"),
    ("Donnie", "Book", 4,"2016-05-16 00:00:00"),
    ("Donnie", "Game", 3,"2016-05-16 00:00:00")

在这种情况下,我需要更新BillyStuff的个人资料并将其更改为" Book"而不是"游戏"因为他在最后一次更新后的最后一条消息中点击了两次相同的类别(profile_actual_timestamp)

所以本周对我来说这是一个非常好的谜题,我想知道你们是否可以帮助我解决这个问题。

originalid = userid(不必要原件,取决于表格)
e.name = profil的名字点击了游戏。

select  originalid,
        name
from   (
        select  @g := if(@u = originalid, if (@p = name, @g, @g + 1), 1) as grp,
                @u := originalid as originalid,
                @p := name as name
        from   (
                select     u.originalid, 
                           m.message_sendtime_timestamp,
                           e.name
                from       bienvenue_nouveau_client_dev u
                inner join messages_nouveaux_clients m
                        on m.originalid = u.originalid
                inner join events_clicked_data e
                        on e.originalId = u.originalid
                       and e.deliveryId = m.deliveryId
                where      m.message_sendtime_timestamp >= u.profil_actuel_timestamp
                and        m.clicked = 'TRUE'
                limit      1000000000000000
                order by   u.originalid,
                           m.message_sendtime_timestamp desc
               ) alias
        ) alias2
where    grp = 1
group by originalid, name
having   count(*) > 1

无论我改变什么,我都会遇到这样的错误:

1250 - 表' u'其中一个SELECT不能在全局ORDER子句

中使用

1 个答案:

答案 0 :(得分:1)

第一个查询可以按如下方式完成:

select     u.*
from       users u
inner join messages m
        on m.user_id = u.user_id
where      m.timestamp >= u.profile_actual_timestamp
and        m.clicked = 'true'
group by   u.user_id
having     count(m.message_id) > 1

如果这些事件发生的时间晚于上次更新,则第二个查询将为您提供在最后两次点击事件中使用相同配置文件的用户:

select  user_id,
        profile
from    (
        select  @g := 0 + if(@u = user_id, if (@p = profile, @g, @g + 1), 1) as grp,
                @u := user_id as user_id,
                @p := profile as profile  
        from    (
                select     u.user_id, 
                           m.timestamp,
                           e.profile
                from       users u
                inner join messages m
                        on m.user_id = u.user_id
                left join  events_clicked_data e
                        on e.user_id = u.user_id
                       and e.deliveryId = m.delivery_id
                where      m.timestamp >= u.profile_actual_timestamp
                order by   u.user_id,
                           m.timestamp desc
                ) alias
        ) alias2
where grp = 1
group by user_id, profile
having  count(*) > 1

SQL fiddle

此查询依赖于变量,并且有点冒险,因为它必须以指定的顺序返回最里面的结果,并且必须按从上到下的顺序评估中间选择列表(带有变量赋值)。这种情况一直发生,但理论上并不能保证。

内部查询中的(高)limit用于确保应用order by子句,而不是实际限制任何内容。

变量@u和@p跟踪 user_id 配置文件。根据以前的值,计算变量@g:只要 user_id 发生变化,它就会重置为1。否则,如果配置文件没有改变,它将保持相同的值,并且当配置文件确实改变时它会增加。

这样, grp 值可以按照降序时间戳的顺序识别配置文件相同且不间断的组。每个使用的最新组具有数字1,这是外部查询中唯一感兴趣的组。然后外部查询要求该组1具有多个记录(即同一个概要文件不止一次出现)。