hawking8su

环境:MYSQL

问题描述:表A和表B关联,关联字段有cat1、cat2、cat3三个维度;表A是配置表,三个字段肯定有值,表B是事实表,三个字段不一定都有值,但是如果cat2有,则cat1肯定有,以此类推;

需求:将表A和表B关联,如果表B的cat3为空,则用cat1和cat2字段关联,如果cat2为空,则用cat1关联,以此类推。

use mytest;
-- 数据准备
create table mycat01 (
	cat1 varchar(10),
    cat2 varchar(10),
    cat3 varchar(10),
    val1 int
);

create table mycat02 (
	cat1 varchar(10),
    cat2 varchar(10),
    cat3 varchar(10),
    val1 int
);


insert into mycat01
values(\'100\', \'100-100\', \'100-100-1\',22);
insert into mycat01
values(\'100\', \'100-200\', \'100-200-1\',33);
insert into mycat01
values(\'200\', \'200-100\', \'200-100-1\',44);


insert into mycat02
values(\'100\', \'100-100\', \'100-100-1\',22);
insert into mycat02
values(\'100\', \'100-200\', null,66);
insert into mycat02
values(\'200\', null, null,88);

-- 直接关联:会出现缺失
select a.*, b.cat1 
from mycat01 a 
left join mycat02 b on a.cat1=b.cat1 and a.cat2=b.cat2 and a.cat3=b.cat3;

-- 解法1:写多个left join; 优点:可读性强;缺点:重复性高,left join次数多执行效率低。
select  a.*, b1.*, b2.*, b3.* 
from mycat02 a 
left join  mycat01 b1 on a.cat1 is not null and a.cat2 is not null and a.cat3 is not null
	and a.cat1=b1.cat1 and a.cat2=b1.cat2 and a.cat3=b1.cat3
left join  mycat01 b2 on a.cat1 is not null and a.cat2 is not null and a.cat3 is null
	and a.cat1=b2.cat1 and a.cat2=b2.cat2 -- and a.cat3=b.cat3
left join  mycat01 b3 on a.cat1 is not null and a.cat2 is null and a.cat3 is null
	and a.cat1=b3.cat1; -- and a.cat2=b.cat2 and a.cat3=b.cat3;


-- 解法2:将cat1-3拼起来,然后用like关联。
-- 把mycat01当做主表 
select a.*, b.cat_full, b.val1
from (select concat(cat1, \'_\', cat2, \'_\', cat3) as cat_full, val1 from mycat01) a 
left join (
	select concat(cat1, \'_\'
			, if(coalesce(cat2,\'\')<>\'\', concat(cat2, \'_\'),\'\')
			, coalesce(cat3,\'\')
        ) as cat_full
        , val1 
	from mycat02
) b on a.cat_full like concat(b.cat_full,\'%\'); -- 也可以用 locate(b.cat_full,a.cat_full)=1

-- 如果 mycat02是主表,left join左右对换也同样适用 
select b.*, a.cat_full, a.val1
from (
	select concat(cat1, \'_\'
			, if(coalesce(cat2,\'\'), concat(cat2, \'_\'),\'\')
			, coalesce(cat3,\'\')
        ) as cat_full
        , val1 
	from mycat02
) a 
left join (
	select concat(cat1, \'_\', cat2, \'_\', cat3) as cat_full, val1 from mycat01
) b on b.cat_full like concat(a.cat_full,\'%\');

补充: 如果在Hive里,就不支持join...on里用like做关联,改用locate(),具体见上。

分类:

技术点:

相关文章: