Mysql查询带有范围的n * 2格式的最大记录

时间:2014-10-07 14:57:17

标签: php mysql

指的是我之前的question我问这个新问题有类似的问题。

我有这样的表records

---- ---------     ------
 id     name       points
---- ---------     ------
 1      aaaa         90
 2      bbbb         87
 3      cccc         90
 4      dddd         80
 5      eeee         86
 6      ffff         82
 7      gggg         87
 8      hhhh         85
 10     iiii         86
 11     iiii         86
 12     iiii         86
 13     iiii         86
 14     iiii         87
 15     iiii         73
 16     iiii         86
 17     iiii         73
 18     hhhh         85
 19     hhhh         73
 20     hhhh         73
 21     hhhh         70
 22     hhhh         65
 23     hhhh         70
 24     hhhh         50

形成表格,我想选择具有以下条件的记录

  1. 对于第一个最高记录,最高点将位于最前面。 (但只有一个记录)。我有两个最高点90的记录,这里应该显示最近的一个(最大ID)

  2. 从第二个记录开始,应以(n * 2)的格式检索字段。我的意思是,对于第二个最大记录,我可以允许4个值下降(2 * 2 = 4),在第二个最大记录-10的范围内。即在表格中,我只选择最近的4条记录(最大id),范围为77到87(87-10 = 77)。现在是第3个最大记录,应该小于或等于76(77-1),即在表中它是73.类似于第3个最大值,我可以允许3 * 2 = 6个记录在63-73之内(73 -10 = 63)..等等..

  3. 目前,我正在使用我的另一个问题的回答

    SELECT id, name, points FROM (
        SELECT
        t.*
        , @n := IF(@prev_points != points, @n + 1, @n) AS n
        , @row := IF(@prev_points != points, 1, @row + 1) AS row
        , @prev_points := points
        FROM
        t
        , (SELECT @prev_points := null, @n := 1, @row := 0) var_init_subquery
        ORDER BY points DESC, id DESC
    ) sq
    WHERE row <= CASE WHEN n = 1 THEN 1 ELSE n * 2 END
    ;
    

    但它仅限于同一条记录。是否有可能根据需要在此查询中使用count或任何其他相关函数。希望你帮帮我。

    输出应该如下所示,

    ---- ---------     ------
     id     name       points
    ---- ---------     ------
     3      cccc         90      -- maximum (only one)
    
     14     iiii         87      |
     7      gggg         87      | -- 2nd maximum (allow 2*2 =4 only)
     2      bbbb         87      |
     16     iiii         86      |
    
     20     hhhh         73      |
     19     hhhh         73      | -- 3rd maximum (allow 3*2 =6 only)
     17     iiii         73      |
     14     iiii         73      |
     23     hhhh         70      | and so on for 4th and 5th
     21     hhhh         70      |
    
     24     hhhh         50      | -- 4th 4*2 = 8
    

1 个答案:

答案 0 :(得分:1)

/*Sample data*/
CREATE TABLE t
    (`id` int, `name` varchar(4), `points` int)
;

INSERT INTO t
    (`id`, `name`, `points`)
VALUES
    (1, 'aaaa', 90),
    (2, 'bbbb', 87),
    (3, 'cccc', 90),
    (4, 'dddd', 80),
    (5, 'eeee', 86),
    (6, 'ffff', 82),
    (7, 'gggg', 87),
    (8, 'hhhh', 85),
    (10, 'iiii', 86),
    (11, 'iiii', 86),
    (12, 'iiii', 86),
    (13, 'iiii', 86),
    (14, 'iiii', 87),
    (15, 'iiii', 73),
    (16, 'iiii', 86),
    (17, 'iiii', 73),
    (18, 'hhhh', 85),
    (19, 'hhhh', 73),
    (20, 'hhhh', 73),
    (21, 'hhhh', 70),
    (22, 'hhhh', 65),
    (23, 'hhhh', 70),
    (24, 'hhhh', 50)
;

/*Query*/
(
  SELECT id, name, points, 'maximum (only one)' AS maximum, 'just the max' AS group_range
  FROM t
  ORDER BY points DESC, id DESC
  LIMIT 1
)
UNION ALL
(
SELECT id, name, points, CONCAT(n, ' maximum'), CONCAT('range from ', group_max, ' to ', group_max - 10) FROM (
    SELECT
    t.*
    , @n := IF(points < @group_max - 10, @n + 1, @n) AS n
    , @group_max := IF(@n != @prev_n, @group_max - 11, @group_max) AS group_max

    , @row := IF(@n != @prev_n, 1, @row + 1)
    , IF(@row > @n * 2, 0, 1) AS select_it
    , @prev_n := @n
    FROM
    t
    , (SELECT @prev_n := 2, @max := points, @group_max := (SELECT points FROM t WHERE points != (SELECT MAX(points) FROM t) ORDER BY points DESC LIMIT 1), @n := 2, @row := 0 FROM t ORDER BY points DESC LIMIT 1) var_init_subquery
    WHERE points != @max
    ORDER BY points DESC, id DESC
) sq
WHERE select_it = 1
);

注意,我认为你有点搞砸了你想要的结果。添加了两列来证明:)

/*Result*/
| ID | NAME | POINTS |            MAXIMUM |         GROUP_RANGE |
|----|------|--------|--------------------|---------------------|
|  3 | cccc |     90 | maximum (only one) |        just the max |
| 14 | iiii |     87 |          2 maximum | range from 87 to 77 |
|  7 | gggg |     87 |          2 maximum | range from 87 to 77 |
|  2 | bbbb |     87 |          2 maximum | range from 87 to 77 |
| 16 | iiii |     86 |          2 maximum | range from 87 to 77 |
| 20 | hhhh |     73 |          3 maximum | range from 76 to 66 |
| 19 | hhhh |     73 |          3 maximum | range from 76 to 66 |
| 17 | iiii |     73 |          3 maximum | range from 76 to 66 |
| 15 | iiii |     73 |          3 maximum | range from 76 to 66 |
| 23 | hhhh |     70 |          3 maximum | range from 76 to 66 |
| 21 | hhhh |     70 |          3 maximum | range from 76 to 66 |
| 22 | hhhh |     65 |          4 maximum | range from 65 to 55 |
| 24 | hhhh |     50 |          5 maximum | range from 54 to 44 |

澄清后更新:

(
  SELECT id, name, points, 'maximum (only one)' AS maximum, 'just the max' AS group_range
  FROM t
  ORDER BY points DESC, id DESC
  LIMIT 1
)
UNION ALL
(
SELECT id, name, points, CONCAT(n, ' maximum'), CONCAT('range from ', group_max, ' to ', group_max - 10) FROM (
    SELECT
    t.*
    , @n := IF(points < @group_max - 10, @n + 1, @n) AS n
    , @group_max := IF(@n != @prev_n, points, @group_max) AS group_max

    , @row := IF(@n != @prev_n, 1, @row + 1)
    , IF(@row > @n * 2, 0, 1) AS select_it
    , @prev_n := @n
    FROM
    t
    , (SELECT @prev_n := 2, @max := points, @group_max := (SELECT points FROM t WHERE points != (SELECT MAX(points) FROM t) ORDER BY points DESC LIMIT 1), @n := 2, @row := 0 FROM t ORDER BY points DESC LIMIT 1) var_init_subquery
    WHERE points != @max
    ORDER BY points DESC, id DESC
) sq
WHERE select_it = 1
);

| ID | NAME | POINTS |            MAXIMUM |         GROUP_RANGE |
|----|------|--------|--------------------|---------------------|
|  3 | cccc |     90 | maximum (only one) |        just the max |
| 14 | iiii |     87 |          2 maximum | range from 87 to 77 |
|  7 | gggg |     87 |          2 maximum | range from 87 to 77 |
|  2 | bbbb |     87 |          2 maximum | range from 87 to 77 |
| 16 | iiii |     86 |          2 maximum | range from 87 to 77 |
| 20 | hhhh |     73 |          3 maximum | range from 73 to 63 |
| 19 | hhhh |     73 |          3 maximum | range from 73 to 63 |
| 17 | iiii |     73 |          3 maximum | range from 73 to 63 |
| 15 | iiii |     73 |          3 maximum | range from 73 to 63 |
| 23 | hhhh |     70 |          3 maximum | range from 73 to 63 |
| 21 | hhhh |     70 |          3 maximum | range from 73 to 63 |
| 24 | hhhh |     50 |          4 maximum | range from 50 to 40 |