我有一张包含客户列表的表:
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中创建这种规则吗?
答案 0 :(得分:4)
在当前表中添加新列将无济于事。
您将不得不创建另一个表,用于存储用户访问的所有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。
答案 1 :(得分:1)
我将为用户和accessdate添加一个额外的表。并使业务逻辑更新访问时的逻辑。例如:
用户|访问日期| c_id
答案 2 :(得分:1)
您的“客户”表是有关客户的数据。那应该是全部了。
但是,您的选择条件实际上是不是看起来是。您要实现的业务需求是供稿或管道,其中选择作为消费者,由未访问的客户供稿。
每个用户(或一组用户,即“一组用户”)都需要它自己的提要,但是可以由具有区分字段的单个表来管理。因此,我们需要一个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
要读取客户数据时,必须执行三个查询:
所以,假设我们正在使用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'
答案 3 :(得分:0)
在客户表中添加一个新列(如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将是用户开始访问资源时将保存的列。
答案 4 :(得分:0)
在表中添加日期时间戳,然后从中进行查询。
答案 5 :(得分:0)
也许有一种方法可以让您轮流使用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上进行的测试