MySQL从联接表中选择特定条目

MySQL selecting specific entries from joined table

提问人:Piotr Kaczmarzyk 提问时间:10/30/2023 最后编辑:nickharPiotr Kaczmarzyk 更新时间:11/1/2023 访问量:30

问:

我有一个表,其中包含用户对特定服务的订阅,按月计费。 还有一个“暂停”表 - 带有“开始”和“结束”日期,用于存储有关用户暂时暂停其订阅的信息。

有三种可能的情况:

  • “开始”和“结束”日期都是过去的 - 用户过去曾暂停订阅一段时间,但现在订阅再次处于活动状态
  • “from”是过去的,但“to”是将来的或为 NULL - 服务目前暂停(直到“to”日期或无限期)
  • “from”和“to”是将来的(或者“from”是将来的,“to”为NULL) - 用户请求将来暂停/取消订阅,但目前服务仍处于活动状态

对于给定的订阅,在“暂停”中可能有多个条目,有些可能已经完成(过去),有些可能“正在进行中”。

现在,我需要选择活动订阅。

我试着做这样的事情:

SELECT * FROM service 
LEFT JOIN suspensions ON service.id = suspensions.service_id 
WHERE 
  suspensions.id IS NULL 
OR 
  ( suspension_from < CURDATE() AND suspension_to < CURDATE() ) 
OR ( suspenstion_from > CURDATE() AND ( suspension_to > CURDATE() OR suspension_to IS NULL)) ) 
GROUP BY 
   service.customer_id

如果给定服务的“暂停”表中只有一个条目,则有效。

但是,如果客户有多个暂停条目,其当前结果不同,例如从 2021 年 1 月 1 日到 2021 年 12 月 31 日和 2023 年 1 月 9 日至 2024 年 8 月 31 日,则 WHERE 子句将第一个条目视为“活动服务”(过去暂停),第二个条目视为“当前不活动”(并按预期省略该条目),结果我将该服务视为活动服务(因为第一个条目), 而实际上它是不活跃的。

如何做到这一点?以某种方式计算(或连接)“活动”结果和“非活动”结果,按customer_id分组,然后仅过滤那些具有 0 个非活动结果的结果?

mysql join select group-concat group

评论

0赞 Ivo P 10/30/2023
如果某个service_id在表格中没有条目暂停怎么办?这可能吗?(我已经看到了 where suspension_id is null 部分......所以是的
0赞 Piotr Kaczmarzyk 10/30/2023
如果没有暂停条目,则服务处于活动状态(从未暂停)
0赞 Piotr Kaczmarzyk 10/30/2023
是的,在论坛上写一个问题以某种方式放松了我的大脑,我找到了答案:)我添加到选择中:SUM(IF ( suspension_from < CURDATE() AND suspension_to < CURDATE(),1,0)) 作为过去,SUM(IF (suspension_from < CURDATE() 和 (suspension_to > CURDATE() 或 suspension_to IS NULL),1,0)) 作为现在,SUM(IF ( suspension_from > CURDATE(),1,0)) 作为未来。现在,我可以使用“当前> 0”创建外部SELECT过滤条目
1赞 Shadow 10/30/2023
我会翻转逻辑并过滤暂停以仅列出非活动订阅,然后使用反加入 (...左加入...哪里。。。是 null) 获取处于活动状态的那些。确定非活动订阅更容易,因为如果您在暂停表中找到任何使订阅现在处于非活动状态的行,则该订阅就不能位于活动列表中。
0赞 Akina 10/30/2023
你的没有意义,并产生逻辑上不正确的查询(和输出)。它只会导致为每个单独的客户返回一个随机的未暂停服务 - 或者如果设置了ONLY_FULL_GROUP_BY模式,则会产生错误。GROUP BY service.customer_id

答:

0赞 Akina 10/30/2023 #1
SELECT * 
FROM service 
LEFT JOIN suspensions ON service.id = suspensions.service_id 
WHERE suspensions.service_id IS NULL 
   OR CURRENT_DATE NOT BETWEEN suspension_from AND COALESCE(suspension_to, CURRENT_DATE) 
-- GROUP BY service.customer_id
-- maybe, ORDER BY service.customer_id ?