如何根据不同的值对MySQL结果进行排名?

时间:2014-06-20 12:08:40

标签: mysql sql

我的数据库中有两个不同的表,名称为:rank,settings。

以下是每个表的外观如下:

表#rank:

id  points userid
--  ----- ------
 1    500      1
 2    300      2    
 3    900      3
 4   1500      4
 5    100      5
 6    700      6
 7    230      7
 8    350      8
 9    850      9
10    150     10

表#settings:

userid    active 
------    ------
     1         0
     2         1
     3         1
     4         1
     5         1
     6         0
     7         1
     8         1
     9         0
    10         1

我基本上想要实现的是从ID中选择#rank中的特定行,按点排序并选择特定ID上方3行和特定ID下方3行但仅适用于活动列的行(来自#settings)用户等于1。

例如: 我想从#rank中选择ID为8,它应该返回以下内容:

rank points userid
---- ----- ------
   2   150     10   
   3   230      7
   4   300      2
   5   350      8
   6   900      3
   7   1500     4

我已经为此创建了相当广泛的查询,但问题是,它在确定用户是否处于活动状态之前对列进行排名。但是,在确定用户是否处于活动状态后,我需要对列进行排名。

SELECT  sub2.sort, sub2.points, sub2.userid
FROM
(
    SELECT  @sort1 := @sort1 + 1 AS sort, puu.points, puu.userid
    FROM    rank as puu,
    (SELECT @sort1 := 0) s
    LEFT JOIN 
    (
        settings as p11 
    )
    ON puu.userid = p11.userid,
    WHERE p11.active = 1
    ORDER BY puu.points DESC
) sub1
INNER JOIN
(
    SELECT @sort2:=@sort2+1 AS sort, p2.points, p2.userid 
    FROM rank as p2,
    (SELECT @sort2 := 0) s
            LEFT JOIN
    (
            settings as p12
    ) 
    ON p2.userid = p12.userid,
    WHERE p12.active = 1
    ORDER BY points DESC
) sub2
ON sub1.userid = :userid
AND sub2.sort BETWEEN (sub1.sort - 5) AND (sub1.sort + 5)

你们能找到解决问题的方法吗?如果你能提供一个SQLfiddle演示,那真是太棒了!

2 个答案:

答案 0 :(得分:1)

SELECT sort, points, user_id, active FROM (
    SELECT @pos := @pos + 1 AS sort, id, points, r.user_id, s.active,
    IF(user_id = :userid, @userpos := @pos, 0)
  FROM rank r
  JOIN settings s USING(user_id)
  JOIN (SELECT @pos := 0, @userpos := 0) p
  WHERE s.active = 1
  ORDER BY points DESC
) list
WHERE sort BETWEEN @userpos - 3 AND @userpos + 3

我在这里做了一个小提琴:sqlfiddle

答案 1 :(得分:0)

可能使用2个联合查询来获取排名前的值: -

SELECT @rank:=@rank+1 AS rank, points, userid
FROM
(
    SELECT id, points, userid
    FROM
    (
        SELECT rank.id, rank.points, rank.userid
        FROM rank
        INNER JOIN
        (
            SELECT points
            FROM rank
            WHERE id = 8
        ) sub0
        ON rank.points >= sub0.points
        INNER JOIN settings
        ON rank.userid = settings.userid
        WHERE settings.active = 1
        ORDER BY rank.points LIMIT 3
    ) sub1
    UNION ALL
    SELECT id, points, userid
    FROM
    (
        SELECT rank.id, rank.points, rank.userid
        FROM rank
        INNER JOIN
        (
            SELECT points
            FROM rank
            WHERE id = 8
        ) sub0
        ON rank.points < sub0.points
        INNER JOIN settings
        ON rank.userid = settings.userid
        WHERE settings.active = 1
        ORDER BY rank.points DESC LIMIT 3
    ) sub1
) sub2
CROSS JOIN (SELECT @rank:=0) sub3
ORDER BY points