2

我有一张桌子users

id | name
1  | Mike

我有一个 表rights,它为我的用户提供了一些权限,例如:

id | user | elevation | starts     | ends
1    1      2           1382950736   1383555536

这里我将 Mike 提升到 2 级,从 1382950736 开始,到 1383555536 结束。在这个时间范围内,用户是 2 级。在其他时间,用户是 1 级。

我有一个查询要找出用户的级别:

SELECT IF(`z`.`elevation` IS NULL, 1, `z`.`elevation`) as `elevation`, `users`.`id`
FROM `users`
LEFT JOIN (
   SELECT `user`, `elevation`
   FROM `rights`
   WHERE (`starts` <= $time) AND (`ends` > $time)
   GROUP BY `user`
) as `z` ON `z`.`user` = `users`.`id`

这一切都很棒,而且效果很好。但是,如果某个用户的海拔重叠,我会遇到问题。

例如:让我们想象一下,只是为了一个简单的例子,现在时间是 10

我们创建这个条目:

id | user | elevation | starts     | ends
1    1      2           1            15
2    1      3           5            20

在这种情况下,两个条目都满足(`starts` <= $time) AND (`ends` > $time)条件(当前时间为 10)。在这些情况下,我的 SELECT 查询所做的是它为我的用户返回2 级,尽管他的最新条目是3 级

如何修复我的查询以返回最新级别,而不是任何级别,以防更多级别重叠

4

3 回答 3

2
SELECT COALESCE(z.elevation,1) elevation
     , u.id
  FROM users u
  LEFT 
  JOIN 
     ( SELECT user
            , elevation
         FROM rights x
         JOIN 
            ( SELECT user,MAX(starts) max_starts FROM rights GROUP BY user ) y
           ON y.user = x.user
          AND y.max_starts = x.starts
        WHERE '$time' BETWEEN starts AND ends
     ) z
    ON z.user =  u.id

得到它?

于 2013-10-28T12:38:15.667 回答
0

How about this:

select if(rs.user is null, 1, r.elevation) as elevation, u.id
from users u
left outer join rights r on u.id = r.user
left outer join (
   select user, max(starts) as starts
   from rights
   where (starts <= $time) AND (ends > $time)
   group by user
) rs on r.user = rs.user and r.starts = rs.starts
where r.user is null or (r.user is not null and rs.user is not null);
于 2013-10-28T12:56:34.163 回答
0

我无法真正理解用例背后的逻辑,但为什么不使用

order by elevation desc
limit 1;
于 2013-10-28T12:42:13.187 回答