MySQL不返回相同的结果

我有一张包含客户列表的表:

customer

c_id    c_name      c_email     c_role
1       abc1        a1@abc.com  Dev
2       abc2        a2@abc.com  Dev
3       abc3        a3@abc.com  Dev
4       abc4        a4@abc.com  Dev
5       abc5        a5@abc.com  Dev
6       abc6        a6@abc.com  Dev
7       abc7        a7@abc.com  Dev
8       abc8        a8@abc.com  Dev
9       abc9        a9@abc.com  Dev

我通过以下方式查询表:

select * from customer where c_role = 'Dev' order by c_id limit 2;

所以,我得到的结果是:

c_id    c_name      c_email     c_role
1       abc1        a1@abc.com  Dev
2       abc2        a2@abc.com  Dev

业务需求表明,如果一组用户最近3天访问过任何记录,则这些记录不应在后续查询输出中返回。

因此,如果用户在接下来的3天中再次运行查询:

select * from customer where c_role = 'Dev' order by c_id limit 2;

结果应为:

c_id    c_name      c_email     c_role
3       abc3        a3@abc.com  Dev
4       abc4        a4@abc.com  Dev

有人可以帮助我如何在MySQL中创建这种规则吗?

zzxx1z2x 回答:MySQL不返回相同的结果

在当前表中添加新列将无济于事。

您将不得不创建另一个表,用于存储用户访问的所有c_id以及执行查询的日期时间。

CREATE TABLE IF NOT EXISTS `access_record` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,`c_id` INT(11) NOT NULL,// id of the record which user accessed
    `user_id` INT(11) NOT NULL,// id of the user who accessed the record
    `accessed_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
);

因此,每当用户运行下一个查询时,您都可以使用此表来了解用户是否已访问记录,然后使用这些c_id将它们从下一个结果集中排除。

SELECT
    c.c_id,c.c_role,c.c_name,c.c_email
FROM
    customer AS c
WHERE
    c.c_role = 'Dev'
    AND c.c_id NOT IN (
        SELECT
            ar.c_id
        FROM
            access_record AS ar
        WHERE ar.user_id = 1  // ofcourse this will change with each user (current user in your case I assume)
            AND ar.accessed_at > DATE_SUB(NOW(),INTERVAL 3 DAY)
     )
     ORDER BY c.c_id LIMIT 2;

这将为您提供最近3天内未被特定用户访问的所有记录。

我希望这会有所帮助。

在评论中回答@dang的问题

  

运行查询时如何填充access_record?

获取所有记录后,便从这些记录中提取c_id,然后将这些c_id插入 access_record 表中。

在MYSQL中,此查询应该可以解决问题

INSERT INTO access_record (c_id,user_id)

SELECT
    c.c_id,1 // user_id of the user who is fetching records
FROM
    customer AS c
WHERE
    c.c_role = 'Dev'
    AND c.c_id NOT IN (
        SELECT
            ar.c_id
        FROM
            access_record AS ar
        WHERE ar.user_id = 1  // ofcourse this will change with each user (current user in your case I assume)
            AND ar.accessed_at > DATE_SUB(NOW(),INTERVAL 3 DAY)
     )
     ORDER BY c.c_id LIMIT 2;

您还可以通过一个查询获取这些c_id,然后使用第二个查询将这些c_id插入到access_record表中。

如果您的所有记录都在$records中提取,则

$c_ids = array_column($temp,'c_id'); // get all c_ids from fetched record array

现在运行查询以插入所有这些c_id。

,

我将为用户和accessdate添加一个额外的表。并使业务逻辑更新访问时的逻辑。例如:

用户|访问日期| c_id

,

您的“客户”表是有关客户的数据。那应该是全部了。

但是,您的选择条件实际上是不是看起来是。您要实现的业务需求是供稿或管道,其中选择作为消费者,由未访问的客户供稿。

每个用户(或一组用户,即“一组用户”)都需要它自己的提要,但是可以由具有区分字段的单个表来管理。因此,我们需要一个user_group表来对您的“用户集”进行分组。

// user_group
g_id    g_data
201     abc1
202     abc2
203     abc3

我们将需要使用每个客户的访问时间戳来填充customer_feed。我们可以添加外键以在删除客户和user_group时将其删除,但是使用它们时我们将需要更新客户feed。

create table customer_feed (
  c_id int(11) not null,g_id int(11) not null,at timestamp not null,primary key (c_id,g_id),constraint customer_fk foreign key (c_id) references customer on delete cascade
  constraint user_group_fk foreign key (g_id) references user_group on delete cascade,);

// customer_feed
c_id    g_id   at
101     201    2018-11-26 07:40:21
102     201    2018-11-26 07:40:21
103     201    2018-11-26 07:40:22

要读取客户数据时,必须执行三个查询:

  1. 更新当前用户组的提要。
  2. 从供稿中获取用户
  3. 将供稿中的用户标记为已使用。

所以,假设我们正在使用user_group 201。

更新Feed时,可以立即读取Feed的所有新用户,我们给他们提供了一个很早的时间戳。这样我们就可以纪念黑斯廷斯之战...

// 1. update the customer_feed for user_group 201
insert into customer_feed(select c.c_id,201,TIMESTAMP('1066-10-14')
from customer c left join customer_feed f 
on c.c_id = f.c_id and f.g_id=201 where f.c_id is null);

我们从客户和提要中选择...我们仅接受访问日期少于三天的记录。这是您最初使用的查询,但是具有供稿限制。

// 2. read from feed for user_group 201
select c.* from customer c,customer_feed f where c.c_role='Dev'
and f.g_id=201 and f.c_id=c.c_id 
and f.at < date_sub(now(),interval 3 day) limit 2

..现在我们需要将Feed中的值标记为已消耗。因此,我们将选择的c_id收集到c_id列表中,例如:“ 102,103”,并将它们标记为已使用。

// 3. Mark the feed as consumed for user_group 201
update customer_feed set at=now() where g_id=201 and c_id in '102,103'
,

在客户表中添加一个新列(如start_accessing),然后可以运行查询:

SELECT * 
    FROM   customer 
    WHERE  c_role = 'Dev' 
           AND Date_add(start_accessing,INTERVAL 3 day) >= Curdate() 
    ORDER  BY c_id 
    LIMIT  2; 

start_accessing将是用户开始访问资源时将保存的列。

,

在表中添加日期时间戳,然后从中进行查询。

,

也许有一种方法可以让您轮流使用3天而无需更改表格。

通过计算开发者的批次。
然后根据当前日期计算当前的开发批处理。

下面的示例适用于MySql 7.x(无窗口功能)

set @date = current_date;
-- set @date = date('2020-07-04');

set @dayslimit = 3;
set @grouplimit = 2;
set @devcnt = (select count(*) cnt 
       from test_customer 
        where c_role = 'Dev');
set @curr_rnk = ((floor(datediff(@date,date('2000-01-01')) / @dayslimit)%floor(@devcnt / @dayslimit))+1);

select c_id,c_name,c_email,c_role
--,rnk
from
(
   select t.*,case when @rn := @rn +1 then @rnk := ceil((@rn/@grouplimit)%(@devcnt+1/@grouplimit)) end as rnk
   from test_customer t
   cross join (select @rn:=0,@rnk:= null) vars
   where c_role = 'Dev'
   order by c_id
) q
where rnk = @curr_rnk
order by c_id
limit 2;

在妊娠here上进行的测试

本文链接:https://www.f2er.com/3117791.html

大家都在问