【问题标题】:MySQL - Simplify complex query for teacher/student subscribersMySQL - 简化教师/学生订阅者的复杂查询
【发布时间】:2013-06-07 11:57:47
【问题描述】:

对于在线学习网站,教师可以创建他们想教授的任何课程。每门课程都有课程。然后,学生可以订阅这些课程或教师添加的任何未来课程,如果他们愿意的话。学生可以通过以下三种方式订阅老师的课程:

1. 仅订阅所有课程(教师当前和未来的所有课程)ex.subscriber_id 12
2. 订阅所有课程,然后取消订阅个别课程(即使取消订阅所有
   当前的个别课程,他们仍会订阅未来的课程)例如 订阅者 ID 10
3. 仅订阅个别课程ex.subscriber_id 11

subscribed_courses 表如下所示:

subscribed_courses (Table with all member chosen resort services)
teacher_id  subscriber_id  course_id    sub_type
    4            10            0          all
    4            10            1         unsub
    4            10            2         unsub
    4            11            4          sub
    4            12            0          all

当老师添加新课程或课程时,我们需要扫描 subscribed_courses 表,并查看哪些订阅的学生应该收到电子邮件。问题是让以下查询工作以将正确的订阅者 ID 发送到电子邮件。对于这个特定的查询示例,让我们使用 course_id 2,它刚刚添加了一个新课程,我们需要向所有订阅者发送电子邮件。必须有更好的方法来实现这一点:

SELECT DISTINCT subscriber_id 
FROM subscribed_courses
WHERE teacher_id='4'
//AND #1 (sub_type='sub' AND course_id='2') //individually subscribed
      #2 ((sub_type='all' AND course_id='0') AND (sub_type='unsub' AND course_id<>'2')) //subscribed to all, ensure subscriber didn't unsub from this course [all subscribed 1 row + more row(s) for unsub]
      #3 (sub_type='all' AND course_id='0') //all subscribed [if this is one row only for subscriber]

知道如何在我们的情况下获得正确的订阅者 ID 或更好的工作解决方案吗?

【问题讨论】:

  • 查询中的 course_id=2 是什么意思?
  • 我们正在向 course_id 2 个订阅者发送电子邮件。刚刚将其添加到问题中,感谢您的注意。

标签: php mysql schema


【解决方案1】:

已更新尝试更简洁的版本

SELECT subscriber_id
  FROM subscribed_courses
 WHERE teacher_id = 4
   AND course_id IN(0, 2)
 GROUP BY teacher_id, subscriber_id
HAVING SUM(       
       CASE WHEN sub_type = 'all'   THEN 1  ELSE 0  END 
     + CASE WHEN sub_type = 'sub'   THEN 1  ELSE 0  END 
     + CASE WHEN sub_type = 'unsub' THEN -2 ELSE 0  END) > 0

输出:

| SUBSCRIBER_ID |
-----------------
|            12 |

这里是SQLFiddle演示

【讨论】:

  • 你说得对,它看起来确实很残酷而且非常复杂。 ELSE -2 有什么作用?此外,我从未见过 > 0 在 WHERE 子句中使用过。所以有两件事让我担心,我不完全理解查询(用于维护/更改),而且我认为如果表有 100s/1000s+ 的订阅课程,那么在添加的每门课程/课程上运行都会很慢。你怎么看?对于这种情况是否有更有效的解决方案(即使它包括架构更改)?
  • @Maverick 刚刚更新了答案。更简洁的版本,无需自行加入。它应该是有效的。
  • 这看起来更清晰。你能解释一下 unsub 的 -2 部分以及逻辑是如何工作的吗?这对于这个小型测试集非常有用,但它适用于更大的列表吗? (我会在一段时间内使用不同的变量设置对其进行多次测试,只是希望您对此发表意见)
  • @Maverick 恕我直言,它可以在您的数据集上正常工作,但要确保您需要彻底测试它。现在它会为 sub_type 分配一个数字。要订阅,您必须有一个值为“all”+1 的行和(或)一个“sub”+1 的行(这可能使其成为 2)。现在,如果您取消订阅,我们将分配 -2。然后我们计算一个总和,看看它是否 > 0,那么就可以了。如果
  • 我喜欢你简单的逻辑。我会接受你的回答并彻底测试。如果它的行为不同,我会用小提琴报告。感谢您的快速解决方案和解释!
【解决方案2】:

请检查这是否是您需要的。谢谢。

SELECT DISTINCT subscriber_id 
FROM subscribed_courses
WHERE teacher_id='4'
AND ((sub_type='sub' AND course_id='2')
union 
SELECT DISTINCT subscriber_id 
FROM subscribed_courses
WHERE teacher_id='4'
AND ((sub_type='all' AND course_id='0') AND (sub_type='unsub' AND course_id<>'2')) 
union
SELECT DISTINCT subscriber_id 
FROM subscribed_courses
WHERE teacher_id='4'
AND (sub_type='all' AND course_id='0'))

【讨论】:

  • 问题是这会返回subscriber_ids 10 和12。由于subscriber_id 10 单独从课程2 和课程1 中取消订阅,但只应返回12,但被替换为所有其他人。最后一个查询覆盖此解决方案中的中间查询。
猜你喜欢
  • 2012-11-17
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 2011-11-21
  • 2011-12-15
  • 2012-05-30
相关资源
最近更新 更多