我有一张表叫notifications:
notifications
CREATE TABLE `notifications` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL, `type` varchar(20) NOT NULL DEFAULT '', `parent_id` int(11) DEFAULT NULL, `parent_type` varchar(15) DEFAULT NULL, `type_id` int(11) DEFAULT NULL, `etc` NULL PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8;
每个notification都与一个不同的表相关,parent_typefield的值指定了我要用于* join该表的表的名称。所有目标表都有几个相似的列:
notification
parent_type
* join
CREATE TABLE `tablename` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `is_visible` tinyint(1) NOT NULL, `etc` NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
当前,我正在使用此查询来选择通知,通知它们在目标表中存在相关行,并且其is_visible字段为1:
is_visible
1
SELECT n.id, FROM notifications n LEFT JOIN books b ON n.parent_id = b.id AND n.parent_type = 'book' AND b.is_visible = 1 LEFT JOIN interviews i ON n.parent_id = i.id AND n.parent_type = 'interview' AND i.is_visible = 1 LEFT JOIN other tables... WHERE n.user_id = 1 GROUP BY n.id
但是由于它是a LEFT JOIN,如果它与任何表都不匹配,它将返回通知,我该如何重写它,以便它不返回与目标表中的任何行都不匹配的通知?我也尝试了CASE不成功的声明。
LEFT JOIN
CASE
我不是100%肯定语法正确,并且现在没有机会对其进行测试,但是这个想法应该很清楚。
SELECT DISTINCT n.id FROM notifications n JOIN ( (SELECT b.id, 'book' AS type FROM books b WHERE b.is_visible = 1) UNION (SELECT i.id, 'interview' AS type FROM interviews i WHERE i.is_visible = 1) ) ids ON n.parent_id = ids.id AND n.parent_type = ids.type WHERE n.user_id = 1