根据列值连接不同的表

und*_*ned 13 mysql sql

我有一张名为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;
Run Code Online (Sandbox Code Playgroud)

每个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;
Run Code Online (Sandbox Code Playgroud)

目前我正在使用此查询来选择目标表中相关行存在的通知,其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
Run Code Online (Sandbox Code Playgroud)

但是因为它是一个LEFT JOIN它返回通知,如果它匹配任何表,我怎么能重写它,所以它不返回与目标表中的任何行不匹配的通知?我也试过这个CASE声明失败了.

Mar*_*zek 20

我不是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
Run Code Online (Sandbox Code Playgroud)

  • 使用`JOIN`和`UNION`可以解决问题.非常感谢你. (2认同)