使用SQL Union执行复杂的报表查询,这取决于越来越宽松的条件

时间:2015-04-09 21:37:00

标签: mysql report union

我有以下架构(其中一部分与问题有关):

# schema
- table
* table field

# schema
    - mods
        * Id
        * Title
        * Affiliation
        * Attended
    - modusergrades
        * ModId 
        * UserId
        * QuestionValues
        * Grade
        * Accepted
        * Comments
    - users
        * Id
        * Projects
        * Location
        * Grade 
        * TermId 
    - all
        * Email
        * FirstName
        * LastName
        * UserId
        * ModId
        * TermId

一旦mods注册了某个活动,他们就可以参加活动(如果在特定时间内登录,Attended将设置为1)。在那里,他们可以评分一定数量的users,比如maxUsers。如果他们评分(QuestionValues != null && Grade != null)小于maxUsers,我们说他们已经开始评分,如果他们已经评分maxUsers我们说他们已经完成分级。

现在,我希望能够区分以下mods类:

  • mods已注册但未参加的人(即Attended = 0)
  • {li> mods谁有Attended活动但未开始评分(Attended = 1QuestionValues == null && Grade == null) 已开始评分但未完成的
  • mods(因此,上述两个字段的非空值小于maxUsers
  • mods已完成评分(== maxUsers)。

我希望能够获得将所有这些信息放在一个地方的SQL查询。

首先, UNION运算符是否适合此任务?如果没有,我该如何解决这个问题?

其次,如果上一个问题的答案是,那么到目前为止我已经获得了成功mods的{​​{1}}。这是正确的做法吗?

graded

编辑:为了使问题更清晰,我的目标是:

SELECT m.Id, m.Title, m.Attended, a.FirstName, a.LastName, a.Email, a.TermId FROM all a INNER JOIN mods m ON m.Id = a.ModId WHERE m.Id = a.ModId AND Attended = 1 AND (SELECT COUNT(*) FROM modusergrade mug WHERE m.Id = mug.ModId AND QuestionValues IS NOT NULL AND Grade IS NOT NULL AND Accepted = 1) > 5 UNION SELECT m.Id, m.Title, 'Graded' AS Attended, a.FirstName, a.LastName, a.Email, a.TermId FROM all a INNER JOIN mods m ON m.Id = a.ModId WHERE m.Id = a.ModId AND Attended = 1 将是Graded的子集,Started GradingAttended的子集,是Registered的子集。设置符号:

Graded ⊆ Started Grading ⊆ Attended ⊆ Registered

是否可以创建捕获此行为的SQL UNION查询?我需要别的吗?

2 个答案:

答案 0 :(得分:1)

“内部联接”是您正在寻找的。

基本上,您从每个表中执行选择查询,以满足您在该表中查找的内容。 (即从参与者= 0的mods中选择id)并加入它们以找到匹配的ID。

Here is an answered question with some code for you.

答案 1 :(得分:1)

您不需要union查询。您只需要一个具有您正在寻找的分层逻辑的case语句。这需要allmug表中的信息以及modusergrades中的摘要信息。

我没有在表格中看到最大问题值,所以我认为它是某种参数。

您想要的查询类似于:

SELECT m.Id, m.Title, m.Attended, a.FirstName, a.LastName, a.Email, a.TermId,
       (CASE WHEN m.Attended = 0 THEN 'Registered'
             WHEN mug.modid IS NULL THEN 'Attended'
             WHEN mug.numgraded < $maxcnt THEN 'Started'
             WHEN mug.numgraded = $maxcnt THEN 'Finished'
        END) as status
FROM all a INNER JOIN
     mods m
     ON m.Id = a.ModId LEFT JOIN
     (SELECT modid, COUNT(*) as numgraded
      FROM modusergrades mug
      WHERE QuestionValues is not null AND Grade is not null
      GROUP BY modid
     ) mug
     ON mug.modid = m.id