【问题标题】:How to control the max number of row for each record in MYSQL?如何控制MYSQL中每条记录的最大行数?
【发布时间】:2015-08-13 18:55:55
【问题描述】:

表结构为:

user
-----
id

video
------
id

user_views
----------
id
user_id
video_id
create_date

并且user_views可以重复,为了防止数据变得非常庞大,我想限制user_views记录:

每个用户最多可以记录20个user_views,如果超过,将替换最旧的记录,先进先出的方式

问题是,如何构造插入查询?

现在我的方法是使用 PHP

  1. 统计特定用户的行数。
  2. 如果 > 20 ,更新最后一条记录(按 create_date 排序)
  3. 否则,插入新记录

它可以工作,但我想要一种性能更高的方式,即在 MYSQL 中进行一次插入查询。

感谢您的帮助。

【问题讨论】:

  • 没有办法在一个 INSERT 查询中做到这一点。您还必须运行 DELETE。它们都有各自的功能,你不能将它们混合在一起。
  • 考虑使用触发器?
  • 好吧,即使使用触发器也无法完成,因为触发器必须是 before insert 并且条件为 if > 20 它应该更新同一个表,并且不允许在触发器中更新同一个表正在执行其他触发器。
  • @AbhikChakraborty,很好的意见。存储过程如何插入/更新/删除 - 并且只授予用户选择权限?

标签: php mysql sql performance


【解决方案1】:

这是一个简单的解决方案:创建虚拟记录以便始终每个用户有 20 个视图。

insert into user_views (user_id, video_id, create_date)
select id, null, '1920-01-01' from user u
where (select count(*) from user_views uv where uv.user_id = u.id) < 20
union all
select id, null, '1919-01-01' from user u
where (select count(*) from user_views uv where uv.user_id = u.id) < 19
union all
select id, null, '1918-01-01' from user u
where (select count(*) from user_views uv where uv.user_id = u.id) < 18
union all
select id, null, '1917-01-01' from user u
where (select count(*) from user_views uv where uv.user_id = u.id) < 17
union all
...

选择数据以显示它们时,排除虚拟记录:

select *
from user_views
where user_id = 123
and video_id is not null; -- dummy entries have video_id null

“插入”新数据时,使用 UPDATE:

update user_views
set video_id = 456, create_date = current_date()
where id = 
(
  select id 
  from
  (
    select id 
    from user_views
    where user_id = 123
    order by create_date
    limit 1
  ) oldest
);

(由于访问正在更新的同一张表时的限制,MySQL中需要子查询中的子查询。)

这里的 SQL 小提琴:http://sqlfiddle.com/#!9/11f2c4/1

【讨论】:

    猜你喜欢
    • 2015-11-05
    • 1970-01-01
    • 2023-03-31
    • 2016-09-03
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    相关资源
    最近更新 更多