Mysql 如何从结果行中提取所需的行数?

Mysql 如何从结果行中提取所需的行数?,mysql,Mysql,我想通过将结果行中满足条件的行数限制为n来进行提取 有两张桌子 tb_info -------------------------- id(PK) | number | status | -------------------------- 1 | 1 | A | 2 | 1 | B | 3 | 2 | B | 4 | 2 | A | 5 | 3

我想通过将结果行中满足条件的行数限制为n来进行提取

有两张桌子


tb_info
--------------------------
 id(PK) | number | status |
--------------------------
    1   |    1   |    A   |
    2   |    1   |    B   |
    3   |    2   |    B   |
    4   |    2   |    A   |
    5   |    3   |    B   |
    6   |    3   |    A   |
    7   |    4   |    C   |
    8   |    4   |    A   |
    9   |    5   |    C   |
   10   |    6   |    A   |


tb_status
---------------------
 st_id(PK) | status 
---------------------
     1     |    A   
     2     |    B   
     3     |    C   

然后运行查询以获得以下结果:

选择id、编号、状态 从tb_信息
其中number您需要按状态列对结果进行排序,以便

SELECT id, number, status FROM tb_info WHERE number <= 5 ORDER BY id, status 
或者只是

SELECT id, number, status FROM tb_info WHERE number <= 5 ORDER BY status 

应使用变量对每个状态的编号进行排序:

SET @rn := 0;
SET @status := '';
SELECT id, number, `status` FROM (
  SELECT @rn := CASE 
    WHEN @status = `status` THEN @rn + 1 
    ELSE 1
  END AS rn, number, `status`, id,
  @status := `status`   
  FROM tb_info 
  WHERE number <= 5
  ORDER BY `status`, number 
) t
WHERE rn <= 2

这是与@forpas相同的解决方案,包含tb_状态

drop table if exists tb_info,tb_status;
create table tb_info
(id int primary key, number int, status varchar(1));
insert into tb_info values
(    1   ,    1   ,    'A'   ),
(    2   ,    1   ,    'B'   ),
(    3   ,    2   ,    'B'   ),
(    4   ,    2   ,    'A'   ),
(    5   ,    3   ,    'B'   ),
(    6   ,    3   ,    'A'   ),
(    7   ,    4   ,    'C'   ),
(    8   ,    4   ,    'A'   ),
(    9   ,    5   ,    'C'   ),
(   10   ,    6   ,    'A'   ),
(   11   ,    1   ,    'd'   ),
(   12   ,    3   ,    'd'   );

create table tb_status
( st_id int primary key, status varchar(1)); 

insert into tb_status values
(     1     ,    'A'),   
(     2     ,    'B'), 
(     3     ,    'C');

select s.id,s.number,s.status
from tb_status
join
(select t.id,t.number,t.status,
        if(t.`status` <> @p , @rn:=1,@rn:=@rn+1) rn,
        @p:=t.`status` p
from tb_info t
cross join (select @rn:=0,@p:=0) r
order by t.status,t.number 
) s
on s.status = tb_status.status  
where s.rn <= 2
order by s.status,s.rn;

+----+--------+--------+
| id | number | status |
+----+--------+--------+
|  1 |      1 | A      |
|  4 |      2 | A      |
|  2 |      1 | B      |
|  3 |      2 | B      |
|  7 |      4 | C      |
|  9 |      5 | C      |
+----+--------+--------+
6 rows in set (0.00 sec)

注释d已删除。

您使用的是哪一版本的mysql?@p.Salmon mysql版本为5.7.27不是结果。我想我想从满足所需条件的行中得到2行。这个输出是什么?你的答案包含在我的问题中。我想让状态栏的A、B和C各打印2个输出。对于8.0之前的版本-注意,我添加了一个小“+0”以避免隐式的强制转换错误。@草莓为真,用户在评论中说版本是5.7.27,它仍然可以通过重新组织一点来进行修改,以便与5.7和8.0兼容,当然,在8中有更简单的方法可用。0@Strawberry添加+0将结果的状态限制为一种情况。@P.Salmon我意识到不同版本有不同的解决方案。谢谢你的回答,谢谢你对我问题的真诚回答。我把你的答案作为一个测试代码,并做了很多研究。
| id  | number | status |
| --- | ------ | ------ |
| 1   | 1      | A      |
| 4   | 2      | A      |
| 2   | 1      | B      |
| 3   | 2      | B      |
| 7   | 4      | C      |
| 9   | 5      | C      |
drop table if exists tb_info,tb_status;
create table tb_info
(id int primary key, number int, status varchar(1));
insert into tb_info values
(    1   ,    1   ,    'A'   ),
(    2   ,    1   ,    'B'   ),
(    3   ,    2   ,    'B'   ),
(    4   ,    2   ,    'A'   ),
(    5   ,    3   ,    'B'   ),
(    6   ,    3   ,    'A'   ),
(    7   ,    4   ,    'C'   ),
(    8   ,    4   ,    'A'   ),
(    9   ,    5   ,    'C'   ),
(   10   ,    6   ,    'A'   ),
(   11   ,    1   ,    'd'   ),
(   12   ,    3   ,    'd'   );

create table tb_status
( st_id int primary key, status varchar(1)); 

insert into tb_status values
(     1     ,    'A'),   
(     2     ,    'B'), 
(     3     ,    'C');

select s.id,s.number,s.status
from tb_status
join
(select t.id,t.number,t.status,
        if(t.`status` <> @p , @rn:=1,@rn:=@rn+1) rn,
        @p:=t.`status` p
from tb_info t
cross join (select @rn:=0,@p:=0) r
order by t.status,t.number 
) s
on s.status = tb_status.status  
where s.rn <= 2
order by s.status,s.rn;

+----+--------+--------+
| id | number | status |
+----+--------+--------+
|  1 |      1 | A      |
|  4 |      2 | A      |
|  2 |      1 | B      |
|  3 |      2 | B      |
|  7 |      4 | C      |
|  9 |      5 | C      |
+----+--------+--------+
6 rows in set (0.00 sec)