从选择中获取LIMIT 3

时间:2011-12-17 15:11:15

标签: mysql subquery

请帮助我查询子查询。 我有2张桌子:

  1. 访问次数:id_viz,Data_viz,Medic_id
  2. 医务人员:id_med,Nume,Prenume,Specialty
  3. 其中visits.Medic_id = medics.id_med,

    我需要在2005年找到前3名医生作为每个专业的访问次数。

    我成功获得的是每个军医的访问次数/每个专业/但是我不知道如何找到每个专业的前三个:(。

    这是我到目前为止所做的:

    SELECT
      CONCAT(m.Nume,' ',m.Prenume) AS Medic,
      m.Specialty,
      COUNT(v.Data_viz) AS nrviz
    FROM
      visits v
    INNER JOIN
      medics m
    ON(v.Medic_id=m.id_med)
    WHERE
      YEAR(v.Data_viz) = 2005
    GROUP BY
      Medic
    ORDER BY
      m.Specialty,
      nrviz DESC
    

    我尝试过LIMIT 3,但当然不行。我认为有必要使用子查询,但我不知道如何。请帮帮我。

2 个答案:

答案 0 :(得分:1)

在其他RDBMS(如PostgreSQL,Oracle或SQL Server)中,您可以使用SQL标准中定义的窗口函数来优雅地解决这个问题。但MySQL不提供此功能。

PostgreSQL 的示例:

SELECT specialty, medic, nrviz
FROM (
    SELECT m.specialty
          ,array_to_string(ARRAY[m.nume,m.prenume], ' ') AS medic
          ,count(v.data_viz) AS nrviz
          ,row_number() OVER (PARTITON BY m.specialty
                              ORDER BY count(v.data_viz) DESC) AS rn
    FROM   visits v
    JOIN   medics m ON (v.medic_id = m.id_med)
    WHERE  year(v.data_viz) = 2005
    GROUP  BY m.specialty, m.nume, m.prenume
    ) x
WHERE  rn <= 3
ORDER  BY specialty, nrviz DESC, medic;

在MySQL中,您必须使用会话变量替换一些黑魔法,就像您在this site上找到的那样。

编辑:

每个专业的前3名医生看起来像 for MySQL (未经测试):

SELECT x.*
FROM  (SELECT @lim := 3, @spc := '') vars,
    (
    SELECT m.specialty
          ,concat(m.nume,' ',m.prenume) AS medic
          ,count(v.data_viz) AS nrviz
    FROM   visits v
    JOIN   medics m ON (v.medic_id = m.id_med)
    WHERE  year(v.data_viz) = 2005
    GROUP  BY 1, 2
    ORDER  BY 1, 3 DESC
    ) x
WHERE  CASE WHEN @spc <> x.specialty
            THEN @r := @lim
            ELSE @r := @r - 1
       END > 0
AND    (@spc := x.specialty) IS NOT NULL
ORDER  BY x.specialty, x.nrviz DESC, x.medic

specialty@spc)的变量初始化为空字符串 - 假设它从不持有空字符串。否则初始化为其他一些不可能的值。还假设specialty NOT NULL

这会查看查询的有序结果并从@lim(3)开始倒计时,因此每个专业只需要前三名医生(访问次数最多)。只要专业发生变化,计数就会重置为@lim

MySQL正在以这种方式将会话变量的过程元素隐藏到基于集合的SQL中。我称之为黑魔法,但它应该完成工作。

答案 1 :(得分:0)

这是您的查询在子查询中的样子:

SELECT
CONCAT(m.Nume,' ',m.Prenume) AS Medic,
  m.Specialty,
COUNT(v.Data_viz) AS nrviz
FROM
  visits v
INNER JOIN
  medics m
ON(v.Medic_id=m.id_med)
WHERE
YEAR(v.Data_viz) = (SELECT...)
GROUP BY
  Medic
ORDER BY
  m.Specialitate,
  nrviz DESC

有关子查询的知识是它们在主查询之前执行,

希望这有帮助!