Mysql:如何找到目前在房间里的用户?

时间:2016-08-28 10:28:40

标签: mysql

我有表entrances,用于记录用户进入房间并走出房间的时间。这样的事情:

user   |   action    |    time
-------------------------------------------
Ivan   |   in        |  2016-08-28 12:00:00 
John   |   in        |  2016-08-28 12:00:01
Ann    |   in        |  2016-08-28 12:00:02
Ivan   |   out       |  2016-08-28 12:00:03
Ivan   |   in        |  2016-08-28 12:00:04
Ann    |   out       |  2016-08-28 12:00:05
Ivan   |   out       |  2016-08-28 12:00:06
Mike   |   in        |  2016-08-28 12:00:07
John   |   out       |  2016-08-28 12:00:08
Ann    |   out       |  2016-08-18 12:00:09
John   |   in        |  2016-08-18 12:00:10
John   |   out       |  2016-08-18 12:00:11
Ann    |   in        |  2016-08-18 12:00:12

用户操作是独立的。只知道第一个操作总是in,用户无法in两次out(并反转)。

我的目标是找到目前在场的所有用户。

我有两个想法:

  1. 选择最新out
  2. 后没有in的用户
  3. 选择计数in的计数为out
  4. 的用户

    如何在mysql上实现这个?还是其他任何想法?

    用于测试的SQL:

    CREATE TABLE `entrances` (
      `id` int(11) NOT NULL,
      `user` varchar(10) COLLATE utf8_bin NOT NULL,
      `action` varchar(3) COLLATE utf8_bin NOT NULL,
      `time` datetime NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
    INSERT INTO `entrances` (`id`, `user`, `action`, `time`) VALUES
    (1, 'Ivan', 'in', '2016-08-28 12:00:00'),
    (2, 'John', 'in', '2016-08-28 12:00:01'),
    (3, 'Ann', 'in', '2016-08-28 12:00:02'),
    (4, 'Ivan', 'out', '2016-08-28 12:00:03'),
    (5, 'Ivan', 'in', '2016-08-28 12:00:04'),
    (6, 'Ann', 'out', '2016-08-28 12:00:05'),
    (7, 'Ivan', 'out', '2016-08-28 12:00:06'),
    (8, 'Mike', 'in', '2016-08-28 12:00:07'),
    (9, 'John', 'out', '2016-08-28 12:00:08'),
    (10, 'Ann', 'out', '2016-08-28 12:00:09'),
    (11, 'John', 'in', '2016-08-28 12:00:10'),
    (12, 'John', 'out', '2016-08-28 12:00:11'),
    (13, 'Ann', 'in', '2016-08-28 12:00:12');
    ALTER TABLE `entrances` ADD PRIMARY KEY (`id`);
    

4 个答案:

答案 0 :(得分:5)

  1. 首先从子查询
  2. 中的每个time获取最后一个操作user
  3. 然后加入该子查询,只包含每个user
  4. 的最后一条记录
  5. 然后只记录那些action = inwhere子句
  6. 的记录

    喜欢这个

    select e.*
    from entrances e
    join
    (
       select user, max(time) as mtime
       from entrances
       group by user
    ) t on t.user = e.user 
       and t.mtime = e.time
    where e.action = 'in'
    

答案 1 :(得分:1)

使用操作<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>加入所有行,并选择没有out操作或out操作更新

的行
in

答案 2 :(得分:0)

我会尝试这样的事情,但是测试真实数据会更好。

select user from entrances e inner join 
(select user, count(*) cnt from entrances where action='in') as e_in 
on e.user=e_in.user left join 
(select user, count(*) cnt from entrances where action='out') as e_out 
on e.user=e_out.user
where e_out.user is null or (e_in.cnt - e_out.cnt) = 1

答案 3 :(得分:0)

我的想法1的Mysql实现:

SELECT e.* FROM entrances e
WHERE NOT EXISTS (
    SELECT * FROM entrances WHERE e.user=user AND action="out" AND time > (
        SELECT MAX(time) FROM entrances WHERE e.user=user AND action="in"
    )
)

这按照字面意思书写:找到在out之后没有in的用户。利用NOT EXISTS功能。优点是可读性,没有魔法,简单的algorythm。