Mysql全外连接两个子查询
Posted
技术标签:
【中文标题】Mysql全外连接两个子查询【英文标题】:Mysql Full outer join two subqueries 【发布时间】:2021-07-13 03:06:25 【问题描述】:我知道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 得到重复的记录,第一条记录的值是另一个 null。我尝试通过添加 case/when account_meta_id 是否相同来做到这一点
【问题讨论】:
编辑您的问题并显示您正在讨论的查询。例如,join
的键是什么?
account_meta_id,account_id 是连接两个表的键
【参考方案1】:
左连接/右连接绝对不是模拟完全连接的最佳方式(它既太昂贵,又会产生删除重复结果的开销,这很愚蠢)。
一种方法是构造所有键,然后只使用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>;
【讨论】:
不能用with,mysql 5.7中的数据以上是关于Mysql全外连接两个子查询的主要内容,如果未能解决你的问题,请参考以下文章