1

我有几个不同的 SQL 表,我需要在这些表上执行一些计数。这是为了我的工作,所以显然数据是机密的,但我会尝试将其抽象为类似的东西。想象一下大学注册办公室...

我们的第一个表包含学生已完成的所有课程的列表。

桌子:student_courses

student_id | course_id
----------------------
123456     | MATH101
123456     | MATH203
785426     | PHYS305
  ...      |   ...

我们还为我们大学的不同部门提供表格,列出(除其他外)课程 ID 和课程年级:

桌子:math_courses

course_id | year
--------------------
MATH101   |  1
MATH201   |  2
MATH202   |  2
CALC103   |  1
STAT402   |  4
 ...      |  ...

想象一下类似science_courses的和general_courses表格。这所大学还有其他部门,但我们现在只考虑这三个。

我们正在寻找的是有多少学生达到了每个年级/部门的组合。

例如,如果学生同时参加了 MATH101 和 MATH201,则他们在数学系的“年”将被视为“2”。

并非所有学生都完成了所有系的课程,也并非所有学生都必须参加这三个系的任何课程。

基本上,我希望生成下表:

max_math_year | max_science_year | max_general_year | student_count
---------------------------------------------------------------------
NULL          | NULL             | NULL             | 39847
NULL          | NULL             | 1                | 172
NULL          | NULL             | 2                | 0
 ...          |  ...             |  ...             |  ...
4             | 4                | 4                | 4986

我已经建立了一个临时表来存储每个学生的最高级别,它似乎工作正常,所以为了这个练习,假设我们有下表:

桌子:#student_maximums

student_id | max_math_year | max_science_year | max_general_year
----------------------------------------------------------------
123465     | 2             | NULL             | 1
782514     | 3             | 1                | NULL
874252     | NULL          | NULL             | NULL
 ...       |  ...          |  ...             |  ...

当一行没有适合特定组合的学生时,我想返回0,但如果我对上表进行计数,它不会返回零值。

大多数时候我会做一个LEFT OUTER JOIN包含零的操作,但在这种情况下,我们计算的是最初来自四个不同表的数据。我考虑过使用 aCROSS JOIN但它不会NULL在行中包含我也需要的值。

谢谢!

4

3 回答 3

4

如果我理解正确,我不确定,但这是你想要的吗?

select
   coalesce(max_math_year, 0)
  ,coalesce(max_science_year, 0)
  ,coalesce(max_general_year, 0)
  ,count(*)
from #student_maximums
group by 
   coalesce(max_math_year, 0)
  ,coalesce(max_science_year, 0)
  ,coalesce(max_general_year, 0)
于 2013-09-16T21:26:46.093 回答
1

我认为这就是您所需要的(尽管我不确定-如果不能解释问题所在):

UPDATE #student_maximums SET max_math_year = 0 WHERE max_math_year is NULL
UPDATE #student_maximums SET max_science_year = 0 WHERE max_science_year is NULL
UPDATE #student_maximums SET max_general_year = 0 WHERE max_general_year is NULL

SELECT max_math_year, max_science_year, max_general_year, count(*) as student_count
FROM #student_maximums
GROUP BY max_math_year, max_science_year, max_general_year
ORDER BY 1, 2, 3
于 2013-09-16T22:04:50.040 回答
0

基于这两个建议,我提出了以下建议。我对合并的值执行了连接,以便空行实际上会在表中排列。

请注意,我能够在课程表中插入行。如果不是,我将联合查询中的零值行。

INSERT INTO math_courses (0, NULL)
INSERT INTO science_courses (0, NULL)
INSERT INTO general_courses (0, NULL)

SELECT
    COALESCE(m.max_math_year, 0)
  , COALESCE(s.max_science_year, 0)
  , COALESCE(g.max_general_year, 0)
  , COUNT(DISTINCT student_id)
FROM
    math_courses m
CROSS JOIN
    science_courses s
CROSS JOIN
    general_courses g
LEFT OUTER JOIN
    student_maximums sm
  ON COALESCE(sm.max_math_year, 0) = COALESCE(m.year, 0)
  AND COALESCE(sm.max_science_year, 0) = COALESCE(s.year, 0)
  AND COALESCE(sm.max_general_year, 0) = COALESCE(g.year, 0)
GROUP BY
    COALESCE(m.max_math_year, 0)
  , COALESCE(s.max_science_year, 0)
  , COALESCE(g.max_general_year, 0)
ORDER BY
    COALESCE(m.max_math_year, 0)
  , COALESCE(s.max_science_year, 0)
  , COALESCE(g.max_general_year, 0)
于 2013-09-19T17:22:21.520 回答