Mysql全外连接两个子查询

时间:2021-04-18 20:39:19

标签: jquery mysql sql database

我知道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 来做到这一点

1 个答案:

答案 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>;