SQL查询使用两个表显示最小平均值和标题

时间:2019-02-21 18:06:50

标签: sql oracle

我有两个表:

import re
regex = r"\[\[[^]]+\]\]|\w+"
test_str = "My son's birthday [[David | David Smith]] $$ (is) \"today\" 2019 ]["
res = re.findall(regex, test_str)
print(' '.join(res))
# My son s birthday [[David | David Smith]] is today 2019

我需要向大学展示最低的平均GPA。

我已经能够提出这个查询:

huffman_students (
id (PK),
fname,
lname,
status ("freshman", "sophomore", "junior", "senior"),
majorcode (FK - huffman_departments.deptcode),
gpa,
admittedDate)

huffman_departments (
deptcode (PK),
deptname,
college)

哪个给出输出:

SELECT MIN(avg_gpa)
FROM
(
SELECT d.college, AVG(s.gpa)
FROM huffman_departments d, huffman_students s
WHERE s.majorcode = d.deptcode
GROUP BY d.college
);

我需要如下输出:

MIN(AVG_GPA)
------------
       3.436

我尝试了很多不同的查询,并不断出错。当试图向大学展示平均平均GPA最低的大学时,我遇到的一个常见错误是:“不是单组分组函数。”

我正在使用Oracle SQL Plus。

4 个答案:

答案 0 :(得分:2)

您可以使用通用表表达式

dump/3

如果您使用的是mysql

with cte0 as 
(
  SELECT d.college, AVG(s.gpa) agpa
  FROM huffman_departments d, huffman_students s
  WHERE s.majorcode = d.deptcode
  GROUP BY d.college
)
select * from cte0  c
where c.college (
  select ci.college from cte0 ci
  group by ci.college 
  having min(ci.agpa) = a.gpa
)

答案 1 :(得分:1)

您可以将现有查询移至子查询(或CTE),然后使用分析功能ROW_NUMBER过滤相关记录:

WITH cte AS (
    SELECT d.college, AVG(s.gpa) avg_spa
    FROM 
        huffman_departments d
        INNER JOIN huffman_students s ON s.majorcode = d.deptcode
    GROUP BY d.college
)
SELECT *
FROM (
    SELECT c.*, ROW_NUMBER() OVER(ORDER BY avg_spa) rn
    FROM cte c
) x WHERE rn = 1

PS:始终使用显式JOIN而不是隐式(CROSS JOIN + WHERE子句)。我相应地更改了查询。

答案 2 :(得分:1)

从不FROM子句中使用逗号。 始终使用正确的,明确的,标准 JOIN语法。

如果要查找一行,可以使用ORDER BYFETCH FIRST 1 ROW ONLY

SELECT d.college, AVG(s.gpa)
FROM huffman_departments d JOIN
     huffman_students s
     ON s.majorcode = d.deptcode
GROUP BY d.college
ORDER BY AVG(s.gpa)
FETCH FIRST 1 ROW ONLY;

如果您希望在发生平局时看到多行,则有多种方法。在MySQL 8+中,窗口函数可能是最简单的方法。在早期版本中,双重聚合可能是最简单的:

SELECT avg_gpa, LISTAGG(college, ',') WITHIN GROUP (ORDER BY college) as colleges
FROM (SELECT d.college, AVG(s.gpa) as avg_gpa
      FROM huffman_departments d JOIN
           huffman_students s
           ON s.majorcode = d.deptcode
      GROUP BY d.college
     ) c
ORDER BY avg_gpa
FETCH FIRST 1 ROW ONLY;

编辑:

较旧的Oracle版本不支持FETCH FIRST。因此,您可以这样做:

SELECT college, avg_gpa
FROM (SELECT d.college, AVG(s.gpa) as avg_gpa,
             ROW_NUMBER() OVER (ORDER BY AVG(s.gpa)) as seqnum
      FROM huffman_departments d JOIN
           huffman_students s
           ON s.majorcode = d.deptcode
      GROUP BY d.college
     ) c
WHERE seqnum = 1
ORDER BY AVG(s.gpa);

答案 3 :(得分:0)

使用您已有的东西

SELECT b.*
FROM  (SELECT d.college, AVG(s.gpa) avg_gpa
FROM huffman_departments d, huffman_students s
WHERE s.majorcode = d.deptcode
GROUP BY d.college
) b
WHERE b.avg_gpa = (SELECT MIN(a.avg_gpa)
FROM
(
SELECT d.college, AVG(s.gpa) avg_gpa
FROM huffman_departments d, huffman_students s
WHERE s.majorcode = d.deptcode
GROUP BY d.college
) a);