0

这是我的表的SQLFiddle 链接

num我基本上只想选择 Jack 和 Jill,因为表的最后两个s 条目foouser它们各自的名称之间存在非零差异。

这怎么可能?

注意:顺便提一下,在我的foo表中,我有大约 100000 行,所以如果有一种非常快速和快速的方法来检索数据会很好。

4

3 回答 3

1

我更喜欢使用limit偏移量来获取两个最新值。令人高兴的是,您的表格有一个id用于确定顺序的列。

select user,
       (select num from foo f2 where f2.user = f.user order by f2.id desc limit 1
       ) lastval,
       (select num from foo f2 where f2.user = f.user order by f2.id desc limit 1, 2
       ) lastval2
from foo f
group by user
having lastval <> lastval2
于 2013-03-28T11:01:22.793 回答
0

这是一种方法(尽管我认为您更有可能加入用户的 id 而不是他们的名字!?!...

SELECT u.* 
  FROM
     ( SELECT x.*, COUNT(*) rank FROM foo x JOIN foo y ON y.user = x.user AND y.id >= x.id GROUP BY x.id)a
  LEFT
  JOIN
     ( SELECT x.*, COUNT(*) rank FROM foo x JOIN foo y ON y.user = x.user AND y.id >= x.id GROUP BY x.id)b
    ON b.user = a.user 
   AND b.num = a.num
   AND b.rank = a.rank + 1
  JOIN users u
    ON u.user = a.user
 WHERE b.id IS NULL
   AND a.rank = 1;

我认为这个查询可以重写如下,这可能会更快......

SELECT u.* 
  FROM
     ( SELECT id
            , user
            , num
            , @prev_user := @curr_user
            , @curr_user := user
            , @rank := IF(@prev_user = @curr_user, @rank+1, @rank:=1) rank
         FROM foo
         JOIN (SELECT @curr_user := null, @prev_user := null, @rank := 0) sel1
        ORDER 
           BY user
            , id DESC
     ) a
  LEFT
  JOIN
       ( SELECT id
            , user
            , num
            , @prev_user := @curr_user
            , @curr_user := user
            , @rank := IF(@prev_user = @curr_user, @rank+1, @rank:=1) rank
         FROM foo
         JOIN (SELECT @curr_user := null, @prev_user := null, @rank := 0) sel1
        ORDER 
           BY user
            , id DESC
     ) b
    ON b.user = a.user 
   AND b.num = a.num
   AND b.rank = a.rank + 1
  JOIN users u
    ON u.user = a.user
 WHERE b.id IS NULL
   AND a.rank = 1;
于 2013-03-28T09:05:14.093 回答
0

基于草莓的第二个解决方案,我已经尝试过了。

SELECT user, MIN(num) AS MinNum, MAX(num) AS MaxNum
FROM (   SELECT id
            , user
            , num
            , @prev_user := @curr_user
            , @curr_user := user
            , @rank := IF(@prev_user = @curr_user, @rank+1, 1) AS rank
FROM foo
JOIN (SELECT @curr_user := null, @prev_user := null, @rank := 1) sel1
ORDER BY user, id DESC
) AS Sub
WHERE rank <= 2
GROUP BY user
HAVING MinNum != MaxNum

这将详细信息列为子选择并拒绝排名大于 2 的位置(不幸的是,如果您尝试在子选择中检查,用户变量会给出奇怪的结果)。然后将结果按用户分组,并返回 num 的最小值和最大值。如果它们不同,则返回该行(并且由于每个用户只有 1 或 2 行,因此只有当返回 2 行并且它们具有不同的值时,最小值和最大值才会不同)。

这样做的好处是它避免了将 2 个 100000 个集合相互连接,并且只需要进行一次排名(尽管您希望 MySQL 无论如何都会优化这个 2nd 问题)。

于 2013-03-28T12:17:02.830 回答