从另一个表中选择具有备用有序字段的行

时间:2013-03-27 12:09:46

标签: mysql sql select

给出* students_exam_rooms *表:

+------------+---------+---------+
| student_id | room_id | seat_no |
+------------+---------+---------+
|          1 |      30 |    1001 |
|          2 |      30 |    1002 |
|          3 |      31 |    2001 |
|          4 |      32 |    2002 |
|          5 |      33 |    3001 |
|          6 |      33 |    3002 |
|          7 |      34 |    4001 |
|          8 |      34 |    4002 |
+------------+---------+---------+

和* students_tbl *:

+------------+-------------+------+
| student_id | studen_name | year |
+------------+-------------+------+
|          1 | Eric        |    1 |
|          2 | Mustafa     |    1 |
|          3 | Michael     |    2 |
|          4 | Andy        |    2 |
|          5 | Rafael      |    3 |
|          6 | Mark        |    3 |
|          7 | Jack        |    4 |
|          8 | peter       |    4 |
+------------+-------------+------+

如何从* students_tbl.year *中选择* students_exam_rooms *排序,但是一个接一个地选择:

+--------------+------+
| student_name | year |
+--------------+------+
| Eric         |    1 |
| Michael      |    2 |
| Rafael       |    3 |
| Jack         |    4 |
| Mustafa      |    1 |
| Andy         |    2 |
| Mark         |    3 |
| Peter        |    4 |
+--------------+------+

3 个答案:

答案 0 :(得分:2)

我假设您想按年份的“发生次数”排序,例如年份,例如所有年份的所有第一次出现,按年份排序,然后所有年份的所有第二次出现也按年份排序,依此类推。这将是模拟其他RDBMS的分析/窗口函数的完美案例:

select *
from (
    select 
        s.studen_name,
        s.year,
        ser.*,
        (
            select 1 + count(*)
            from students_tbl s2
            where s.year = s2.year
                and s.student_id > s2.student_id
        ) rank
    from students_tbl s
        JOIN students_exam_rooms ser
            ON s.student_id = ser.student_id
) i_dont_really_want_to_name_this
order by rank, year

这是针对JW小提琴的略微调整的版本:http://www.sqlfiddle.com/#!2/27c91/1

Emulating Analytic (AKA Ranking) Functions with MySQL是一篇很好的文章,提供了更多背景和解释。

答案 1 :(得分:1)

尝试以下任何一项:

SELECT  a.studen_name, a.year
FROM    students_tbl a
        INNER JOIN students_exam_rooms b
          ON a.student_id = b.student_id
ORDER   BY  REVERSE(b.seat_no),
            a.year

使用Modulo

SELECT  a.studen_name, a.year
FROM    students_tbl a
        INNER JOIN students_exam_rooms b
          ON a.student_id = b.student_id
ORDER   BY CASE WHEN MOD(b.seat_no, 2) <> 0 THEN 0 ELSE 1 END,
            a.year

答案 2 :(得分:0)

在我看来,你想要先按座位排序,然后逐年排序。查看您的students_exam_rooms表格,您看起来就像一个简单的座位号码,并且前面有year * 1000。所以,如果我们省略年份,它看起来像这样:

> select * from fixed_students_exam_rooms;
+------------+---------+---------+
| student_id | room_id | seat_no |
+------------+---------+---------+
|          1 |      30 |       1 |
|          2 |      30 |       2 |
|          3 |      31 |       1 |
|          4 |      32 |       2 |
|          5 |      33 |       1 |
|          6 |      33 |       2 |
|          7 |      34 |       1 |
|          8 |      34 |       2 |
+------------+---------+---------+

如果您有那个表,那么您的查询很简单:

select
  student_name, year

from
  modified_student_exame_rooms
  left join students_tbl using (student_id)

order by
  seat_no, year
;

使用当前拥有的,只是稍微复杂一点,假设“核心座位号”不超过999。

select
  student_name, year

from
  modified_student_exame_rooms
  left join students_tbl using (student_id)

order by
  convert(substr(seat_no, 2), unsigned),
  year
;