请帮助我查询子查询。 我有2张桌子:
其中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,但当然不行。我认为有必要使用子查询,但我不知道如何。请帮帮我。
答案 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
有关子查询的知识是它们在主查询之前执行,
希望这有帮助!