dongtan8979 2015-09-15 16:45
浏览 84
已采纳

将PHP依赖的SQL代码转换为完整的SQL

the question will require a bit long of an answer to explain due to my ignorance on SQL. I hope it will not be viewed as vague because I have tried doing it by parts, but then I wont know which part exactly is causing which problem.(It really shows my level of knowledge on SQL.)

I have a code that was originally written in a PHP file, but I have decided I want to create a view table in order for the page to load faster. The reason was because it does a loop to list the ranking of students and was taking too long for the web page to load.

Anyways, here is the code :

    SELECT
      SUM(VCA.meritPoint) AS merit,
      VCA.student_no      AS student_no,
      P.program_code      AS education_level,
      P.name              AS name,
      P.gender            AS gender,
      P.campus_id         AS campus_id
    FROM viewcardactivity VCA
      JOIN pupil P ON P.student_no = VCA.student_no
      JOIN semester S ON S.id = '{$id}' -- MAX() AND (MAX() - 1)
        AND DATE(VCA.tarikh) BETWEEN DATE(s.tarikhStart) AND DATE(s.tarikhEnd)
          WHERE P.campus_id = '{$campus}' -- 1, 2
            AND P.gender= '{$gender}' -- M, F
            AND VCA.level= '{$level}' -- Diploma, Degree
            AND P.program_code = (CONVERT(IF((SUBSTR(REPLACE(`p`.`program_code`,' ',''),3,1) = 1),'Diploma','Degree')USING latin1))
    GROUP BY student_no ORDER BY merit DESC

As the name of the columns suggests, I would like to display more than one instead of specific ids, gender and level provided from the PHP variables.

The example output I would like to have is such as(based on the SQL Fiddle mock data :

table 'viewrankingmerit'   
| merit | student_no | education_level | name | gender | campus_id | 
---------------------------------------------------------------------
|  99   | 111111111  |      Diploma    | Ash  |   M    |     1     | 
---------------------------------------------------------------------
|  87   | 222222222  |      Diploma    |Belle |   F    |     1     | 
---------------------------------------------------------------------
|  85   | 333333333  |      Degree     | Carl |   M    |     1     | 
---------------------------------------------------------------------
|  80   | 444444444  |      Degree     | Deli |   F    |     1     | 
---------------------------------------------------------------------
|  75   | 555555555  |      Diploma    | Eddy |   M    |     2     | 
---------------------------------------------------------------------
|  74   | 666666666  |      Diploma    |Foxxy |   F    |     2     | 
---------------------------------------------------------------------
|  50   | 777777777  |      Degree     | Greg |   M    |     2     | 
---------------------------------------------------------------------
|  20   | 888888888  |      Degree     |Haley |   F    |     2     | 
---------------------------------------------------------------------

As for the semester id, I would like to get the latest 2 ids. Which is the highest and second highest, based on the auto-generated id that will keep on increasing..

I was immediately stuck at trying to get 2 ids from table semester. I've tried using :

JOIN semester S1 ON S1.id = (SELECT MAX(s1.id) FROM semester)
   AND DATE(VCA.tarikh) BETWEEN DATE(s1.tarikhStart) AND DATE(s1.tarikhEnd)

JOIN semester S2 ON S2.id = (SELECT MAX(s2.id)-1 FROM semester)
   AND DATE(VKA.tarikh) BETWEEN DATE(s2.tarikhStart) AND DATE(s2.tarikhEnd)

It was probably a bad reference, but that was the closest solution I got so far.

1) Is it possible to do a table to show all the info?

2) If yes, how to get both S.id, P.campus_id, P.gender and VCA.level. Hoping that the solution would be alike.

3) If no, what is the best solution?

Thanks a lot guys.

[Edit] I've added a demo data in an SQL Fiddle

  • 写回答

1条回答 默认 最新

  • dpda53918 2015-09-18 03:52
    关注

    After some discussion in coments, this is the final result. I think.

    select sum(vca.meritPoint)      as merit,
           vca.student_no      AS student_no,
           vca.type            AS education_level,
           p.name              AS name,
           p.gender            AS gender,
           p.campus_id         AS campus_id
     from
       viewcardactiviti vca
          inner join pupil p ON p.student_no = vca.student_no
          inner join (select * from semester order by id desc limit 2) s
                  ON (vca.tarikh between s.tarikhStart and s.tarikhEnd
                      AND vca.type = s.level)
    group by vca.student_no, vca.type, p.name, p.gender, p.campus_id
    order by merit desc, p.campus_id;
    

    See it here on SQLFiddle

    If you need to filter for specific configurations like the parameters on your original query just add a WHERE clause.

    This subquery (select * from semester order by id desc limit 2) will get the last to semesters based on the ID. And since there is no direct link (foreign key) between semester and viewcardactiviti you can use there join conditions ON (vca.tarikh between s.tarikhStart and s.tarikhEnd AND vca.type = s.level)

    If you think that it still need to change anything let me know!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?