无法理解此SQL查询

时间:2016-08-04 06:09:57

标签: mysql sql

这是Hacerrank上的一个SQL problem的解决方案,但我无法理解这个查询是如何工作的,因为我是这个领域的新手。任何人都可以解释这个或给我链接好的教程,我可以学习这种类型的复杂查询。

SET @d=0,@a=0,@p=0,@s=0;
SELECT MIN(Doctor),MIN(Professor),MIN(SINGER),MIN(Actor)
FROM
(SELECT IF(OCCUPATION='Actor',NAME,NULL) AS Actor, 
        IF(OCCUPATION='Doctor',NAME,NULL) AS Doctor, 
        IF(OCCUPATION='Professor',NAME,NULL) AS Professor, 
        IF(OCCUPATION='Singer',NAME,NULL) AS SINGER,
    case OCCUPATION when 'ACTOR' THEN @a:=@a+1 
                    when 'Doctor' THEN @d:=@d+1 
                    when 'Professor' THEN @p:=@p+1 
                    when 'Singer' THEN @s:=@s+1 
    end
as idn FROM OCCUPATIONS ORDER BY NAME ) AS TMP GROUP BY TMP.idn ;

1 个答案:

答案 0 :(得分:1)

将其拆分为

部分
SET @d=0,@a=0,@p=0,@s=0;

这将设置4个用户变量,将它们初始化为0。

SELECT IF(OCCUPATION='Actor',NAME,NULL) AS Actor, 
        IF(OCCUPATION='Doctor',NAME,NULL) AS Doctor, 
        IF(OCCUPATION='Professor',NAME,NULL) AS Professor, 
        IF(OCCUPATION='Singer',NAME,NULL) AS SINGER,
    case OCCUPATION when 'ACTOR' THEN @a:=@a+1 
                    when 'Doctor' THEN @d:=@d+1 
                    when 'Professor' THEN @p:=@p+1 
                    when 'Singer' THEN @s:=@s+1 
    end
as idn 
FROM OCCUPATIONS 
ORDER BY NAME

这将返回5列。如果该行引用特定职业,则前4列将返回该行的名称。因此,如果该行的职业是“医生”。然后第二列将包含name字段的内容,而第1,3和4列将为NULL。

第5列计算该职业的数量。这可能会也可能不会按名称的顺序进行(MySQL选择将值分配给用户变量的位置未定义) - 它现在可能正常工作,但未来可能不会。但基本上如果将包含该职业数量的连续计数,其中第一个职业包含1和下一个职业,等等。

SELECT MIN(Doctor),MIN(Professor),MIN(SINGER),MIN(Actor)
FROM
(.....) AS TMP GROUP BY TMP.idn ;

这是获取早期SELECT(用作子查询)的结果,并按计数对结果进行GROUP运算。因此,对于每个计数值(最多发生4次,每次占用一次),它将返回每个职业的MIN(按字母顺序排列)名称。 MIN聚合函数通常会忽略NULL值,因此将返回第一个使用的名称。

通过一些虚拟数据来完成。以下面的例子为例: -

id  Name    Occupation
1   freda   Actor
2   fredb   Doctor
3   fredc   Professor
4   fredd   Actor
5   frede   Doctor
6   fredf   Actor
7   fredg   Professor
9   fredh   Singer
10  fredi   Actor
11  fredj   Doctor
12  fredk   Professor
13  fredl   Actor
14  fredm   Doctor
15  fredn   Professor
16  fredo   Professor
17  fredp   Singer
19  fredq   Doctor
20  fredr   Actor

子查询给出: -

Actor   Doctor  Professor   Singer  idn 
freda   NULL    NULL        NULL    1
NULL    fredb   NULL        NULL    1
NULL    NULL    fredc       NULL    1
fredd   NULL    NULL        NULL    2
NULL    frede   NULL        NULL    2
fredf   NULL    NULL        NULL    3
NULL    NULL    fredg       NULL    2
NULL    NULL    NULL        fredh   1
fredi   NULL    NULL        NULL    4
NULL    fredj   NULL        NULL    3
NULL    NULL    fredk       NULL    3
fredl   NULL    NULL        NULL    5
NULL    fredm   NULL        NULL    4
NULL    NULL    fredn       NULL    4
NULL    NULL    fredo       NULL    5
NULL    NULL    NULL        fredp   2
NULL    fredq   NULL        NULL    5
fredr   NULL    NULL        NULL    6

外部查询对此进行操作,每个使用的计数给出一行(即,行数将与占用的最大数量相同,无论哪个占用最多),以及该人员的名称。占领数: -

Doctor  Professor   Singer  Actor
fredb   fredc       fredh   freda
frede   fredg       fredp   fredd
fredj   fredk       NULL    fredf
fredm   fredn       NULL    fredi
fredq   fredo       NULL    fredl
NULL    NULL        NULL    fredr