Mysql左连接,仅当字段is_active = 1时才覆盖行

时间:2012-12-20 18:42:50

标签: mysql join union

上午9点我从之前的帖子中获得了查询的帮助,但我有一个新问题。 在我的解释中忍受我......

设置,2个表:cal_events,用于保存日历的动态事件以及在一天内对其进行更新的重复事件。此外,cal_events_recurring持有重复发生的事件。 下面的查询是一个由PHP传递的虚拟数据的示例。 我是在12月15日之前完成的,因此请返回当天的每个活动。 重要的是,只有在没有匹配的动态对应物的情况下才会返回重复出现的事件。如果cal_eventsis_overwrite = 1且其overwrite_id =(上午9:00 cal_events_recurring事件的唯一ID,则仅返回动态表行。 这意味着,“嘿,我是每天上午9点(例子)发生的事件,但是看看,12月15日9:00重复发生的事件已根据具有我唯一ID的动态表格更新当天=到它的overwrite_id所以返回那个。“

select * from(
    select
        ifnull(ce.time, cer.time) as time,
        ifnull(ce.title, cer.title) as title,
        ce.is_overwrite
    from cal_events_recurring cer
    left join cal_events ce on ce.overwrite_id = cer.id
    where cer.is_daily = 1
    or cer.day_index = 6
    or cer.day_num = 15
    union
    select time as time, title, is_overwrite 
    from cal_events where date = '2012-12-15' 
    and is_active = 1 and is_overwrite = 0) as e order by time asc

这一切都很好,数据是正确的,问题是is_active字段。 我将再次离开上午9点的例子。我在16日上午9点创建了一个动态事件,它将覆盖16日的重复事件。现在,如果我后来决定要恢复到常规重复事件,我会将is_active字段设置为0以匹配动态事件。问题是仍然返回动态事件。如果我添加and ce.is_active = 0,则仍会返回该事件。如果它的动态对应物不活动,我将如何编写它以便仍然返回周期性事件?

您需要的任何其他信息都告诉我们!

编辑* 输出:

time      title 
08:00:00  recurring everyday 8am
09:00:00  dynamic 9am update 

(9am should be the recurring event because the dynamic    is_active = 0)

1 个答案:

答案 0 :(得分:2)

将该条件放入ON子句:

select * from(
    select
        ifnull(ce.time, cer.time) as time,
        ifnull(ce.title, cer.title) as title,
        ce.is_overwrite
    from cal_events_recurring cer
    left join cal_events ce on ce.overwrite_id = cer.id
        and ce.is_overwrite = 1     -- Added this line
    where cer.is_daily = 1
    or cer.day_index = 6
    or cer.day_num = 15
    union
    select time as time, title, is_overwrite 
    from cal_events where date = '2012-12-15' 
    and is_active = 1 and is_overwrite = 0) as e order by time asc
)

将特殊条件置于连接条件意味着您仍然可以获得左连接,但仅适用于应该连接的行。

如果你把条件放在where子句中,你将“打破”左连接的意图和ifnull(),这就是原因:

连接的ON子句中的条件在进行连接时执行,因此您不希望加入的行不会加入,也不会将它们的值放入{{1}功能。

一种常见的误解是,加入条件只能是“关键相关”,实际上它们可以是任何东西。


如果将条件放入where子句,则在进行连接后执行 - 其中子句过滤器结果集,因此为时已晚 - ifnull()已经拥有动态表的数据。