我知道mysql不支持全外连接,这样做你必须基本上左连接/右连接并做联合。我有两个表,一个包含所有可能的带有帐户标签的键,另一个包含帐户中每个客户端的键值。我想获取帐户的所有键,如果它也有值记录值,我想按类型过滤。
CREATE TABLE IF NOT EXISTS `account_meta` (
`account_meta_id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(100) COLLATE utf8mb4_bin NOT NULL,
`key` varchar(200) COLLATE utf8mb4_bin NOT NULL,
`value` varchar(300) COLLATE utf8mb4_bin NOT NULL,
`rank` int(11) DEFAULT NULL,
`account_id` int(11) NOT NULL,
PRIMARY KEY (`account_meta_id`),
KEY `account_id` (`account_id`),
KEY `key` (`key`(191))
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(1, 'contact', 'Facebook', '', 1, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(2, 'contact', 'Instagram', '', 2, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(3, 'contact', 'Phone', '', 3, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(4, 'contact', 'Email', '', 4, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(5, 'contact', 'WeChat', '', 5, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(6, 'stage', 'Sky', '', 6, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(7, 'stage', 'Why', '', 7, 1);
INSERT INTO `account_meta` (`account_meta_id`, `type`, `key`, `value`, `rank`, `account_id`) VALUES(8, 'stage', 'My', '', 8, 1);
CREATE TABLE IF NOT EXISTS `client_contact` (
`client_contact_id` int(11) NOT NULL AUTO_INCREMENT,
`client_id` int(11) NOT NULL,
`account_id` int(11) NOT NULL,
`account_meta_id` int(200) NOT NULL,
`value` varchar(1000) COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`client_contact_id`),
KEY `client_id` (`client_id`),
KEY `key` (`account_meta_id`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `client_contact` (`client_contact_id`, `client_id`, `account_id`, `account_meta_id`, `value`) VALUES(2, 11, 1, 1, 'https://www.yahoo.com');
INSERT INTO `client_contact` (`client_contact_id`, `client_id`, `account_id`, `account_meta_id`, `value`) VALUES(3, 11, 1, 2, 'Serua');
INSERT INTO `client_contact` (`client_contact_id`, `client_id`, `account_id`, `account_meta_id`, `value`) VALUES(4, 11, 1, 3, 'abs');
INSERT INTO `client_contact` (`client_contact_id`, `client_id`, `account_id`, `account_meta_id`, `value`) VALUES(6, 11, 1, 5, 'oragnas');
INSERT INTO `client_contact` (`client_contact_id`, `client_id`, `account_id`, `account_meta_id`, `value`) VALUES(7, 12, 1, 5, 'oragnas');
https://www.db-fiddle.com/f/jHzANXZDjykpSWMcsX5a5f/5
基本上我希望第一个查询结果是到 mysql (5.7) 中第二个查询结果的完全外连接。第三个查询是我尝试这样做,但是无论我做什么,我都无法让它返回。我试过做交叉连接,但得到重复的记录,重复的 account_meta_id,第一条记录的值是另一个空值。如果 account_meta_id 是否相同,我尝试通过添加 case/when 来做到这一点
答案 0 :(得分:0)
左连接/右连接绝对不是模拟完整连接的最佳方式(它既成本太高,又会导致删除重复结果的开销,这很愚蠢)。
一种方法是构造所有的键,然后只使用left join
:
with am as (
select *
from `account_meta`
where account_id = 1 and `type` = 'contact'
),
cc as (
select *
from `client_contact`
where account_id = 1 and client_id = 11
)
select am.*, cc.*
from ((select <key> -- whatever the key is for the join
from am
) union -- on purpose to remove duplicates
(select <key>
from cc
)
) k left join
cc
on cc.<key> = k.<key> left join
am
on am.<key> = k.<key>;