子查询返回空结果时主SELECT查询报错的问题求助
解决子查询返回空时主查询报错的问题
首先咱们先揪出问题根源:当子查询SELECT read_ids FROM read_notifications WHERE user_id = 46没有匹配结果时,会返回NULL,而FIND_IN_SET函数的第二个参数如果是NULL的话,整个函数会返回NULL。在WHERE条件里,NOT NULL会被视为不成立,甚至可能因为函数参数非法直接报错。另外你的SQL里还有个小拼写错误:notisfication_for应该是notification_for,这个也得修正哦。
下面给你几个可行的解决方案:
方案1:用COALESCE处理子查询的空结果
把子查询的结果用COALESCE包裹,当子查询返回NULL时自动替换成空字符串,让FIND_IN_SET能正常工作:
SELECT COUNT(`Notification`.`id`) AS `count` FROM `listaren_mercury_live`.`notifications` AS `Notification` WHERE NOT FIND_IN_SET(`Notification`.`id`, COALESCE((SELECT read_ids FROM read_notifications WHERE user_id = 46), '')) AND ( (notification_for IN("all","India")) OR (FIND_IN_SET(46, notification_for)) )
原理:COALESCE(a, b)会返回第一个非NULL的值,当子查询没结果时就用空字符串代替,FIND_IN_SET(id, '')返回0,NOT 0等价于true,这样所有符合后面条件的通知都会被算作未读。
方案2:改用LEFT JOIN(推荐,性能更优)
这种方式彻底避开了子查询返回空的问题,逻辑也更直观,适合数据量较大的场景:
SELECT COUNT(n.id) AS `count` FROM `listaren_mercury_live`.`notifications` n LEFT JOIN `listaren_mercury_live`.`read_notifications` rn ON rn.user_id = 46 AND FIND_IN_SET(n.id, rn.read_ids) WHERE rn.read_ids IS NULL AND ( n.notification_for IN('all', 'India') OR FIND_IN_SET(46, n.notification_for) )
原理:通过LEFT JOIN关联已读记录,rn.read_ids IS NULL表示当前通知没有被标记为已读,直接筛选出未读的通知进行计数。
方案3:用EXISTS子查询
用EXISTS判断当前通知是否存在于已读列表中,逻辑清晰且稳定:
SELECT COUNT(`Notification`.`id`) AS `count` FROM `listaren_mercury_live`.`notifications` AS `Notification` WHERE NOT EXISTS ( SELECT 1 FROM `read_notifications` rn WHERE rn.user_id = 46 AND FIND_IN_SET(`Notification`.`id`, rn.read_ids) ) AND ( (notification_for IN("all","India")) OR (FIND_IN_SET(46, notification_for)) )
原理:NOT EXISTS会检查是否存在对应的已读记录,不存在的话就保留这条通知,完美避开子查询返回空的问题。
内容的提问来源于stack exchange,提问作者Gyandeep Sharma
相关产品推荐
相关产品推荐

