hadoop多表关联


2.多表关联

多表关联和单表关联类似,它也是通过对原始数据进行一定的处理,从其中挖掘出关心的信息。下面进入这个实例。

实例描述

输入是两个文件,一个代表工厂表,包含工厂名列和地址编号列;另一个代表地址表,包含地址名列和地址编号列。要求从输入数据中找出工厂名地址名对应关系,输出"工厂名——地址名"表。

样例输入如下所示。

1)factory:

factoryname     addressed

Beijing Red Star     1

Shenzhen Thunder     3

Guangzhou Honda     2

Beijing Rising     1

Guangzhou Development Bank2

Tencent         3

Back of Beijing      1

2)address:

addressID addressname

1     Beijing

2     Guangzhou

3     Shenzhen

4     Xian

样例输出如下所示。

factoryname     addressname

Back of Beijing      Beijing

Beijing Red Star     Beijing

Beijing Rising       Beijing

Guangzhou Development BankGuangzhou

Guangzhou Honda     Guangzhou

Shenzhen Thunder     Shenzhen

Tencent         Shenzhen

设计思路

多表关联和单表关联相似,都类似于数据库中的自然连接。相比单表关联,多表关联的左右表和连接列更加清楚。所以可以采用和单表关联的相同处理方式,map识别出输入的行属于哪个表之后,对其进行分割,将连接的列值保存在key中,另一列和左右表标识保存在value中,然后输出。reduce拿到连接结果之后,解析value内容,根据标志将左右表内容分开存放,然后求笛卡尔积,最后直接输出。

这个实例的具体分析参考单表关联实例。下面给出代码。

程序代码

程序代码如下所示:

packagecom.hebut.mr;

importjava.io.IOException;

importjava.util.*;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.Path;

importorg.apache.hadoop.io.IntWritable;

importorg.apache.hadoop.io.Text;

importorg.apache.hadoop.mapreduce.Job;

importorg.apache.hadoop.mapreduce.Mapper;

importorg.apache.hadoop.mapreduce.Reducer;

importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;

importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

importorg.apache.hadoop.util.GenericOptionsParser;

publicclassMTjoin {

publicstaticinttime= 0;

/*

*map中先区分输入行属于左表还是右表,然后对两列值进行分割,

*保存连接列在key值,剩余列和左右表标志在value中,最后输出

*/

publicstaticclassMapextendsMapper<Object, Text, Text, Text> {

//实现map函数

publicvoidmap(Object key, Text value, Context context)

throwsIOException, InterruptedException {

String line = value.toString();//每行文件

String relationtype =newString();//左右表标识

//输入文件首行,不处理

if(line.contains("factoryname") ==true

|| line.contains("addressed") ==true) {

return;

}

//输入的一行预处理文本

StringTokenizer itr =newStringTokenizer(line);

String mapkey =newString();

String mapvalue =newString();

inti = 0;

while(itr.hasMoreTokens()) {

//先读取一个单词

String token = itr.nextToken();

//判断该地址ID就把存到"values[0]"

if(token.charAt(0) >='0'&& token.charAt(0) <='9') {

mapkey = token;

if(i > 0) {

relationtype ="1";

}else{

relationtype ="2";

}

continue;

}

//存工厂名

mapvalue += token +" ";

i++;

}

//输出左右表

context.write(newText(mapkey),newText(relationtype +"+"+ mapvalue));

}

}

/*

* reduce解析map输出,将value中数据按照左右表分别保存,

  *然后求出笛卡尔积,并输出。

*/

publicstaticclassReduceextendsReducer<Text, Text, Text, Text> {

//实现reduce函数

publicvoidreduce(Text key, Iterable<Text> values, Context context)

throwsIOException, InterruptedException {

//输出表头

if(0 ==time) {

context.write(newText("factoryname"),newText("addressname"));

time++;

}

intfactorynum = 0;

String[] factory =newString[10];

intaddressnum = 0;

String[]address=newString[10];

Iteratorite = values.iterator();

while(ite.hasNext()) {

String record = ite.next().toString();

intlen = record.length();

inti = 2;

if(0 == len) {

continue;

}

//取得左右表标识

charrelationtype = record.charAt(0);

//左表

if('1'== relationtype) {

factory[factorynum] = record.substring(i);

factorynum++;

}

//右表

if('2'== relationtype) {

address[addressnum] = record.substring(i);

addressnum++;

}

}

//求笛卡尔积

if(0 != factorynum && 0 != addressnum) {

for(intm = 0; m < factorynum; m++) {

for(intn = 0; n < addressnum; n++) {

//输出结果

context.write(newText(factory[m]),

newText(address[n]));

}

}

}

}

}

publicstaticvoidmain(String[] args)throwsException {

Configuration conf =newConfiguration();

//这句话很关键

conf.set("mapred.job.tracker","192.168.1.2:9001");

String[] ioArgs =newString[] {"MTjoin_in","MTjoin_out"};

String[] otherArgs =newGenericOptionsParser(conf, ioArgs).getRemainingArgs();

if(otherArgs.length!= 2) {

System.err.println("Usage: Multiple Table Join <in> <out>");

System.exit(2);

}

Job job =newJob(conf,"Multiple Table Join");

job.setJarByClass(MTjoin.class);

//设置MapReduce处理类

job.setMapperClass(Map.class);

job.setReducerClass(Reduce.class);

//设置输出类型

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(Text.class);

//设置输入和输出目录

FileInputFormat.addInputPath(job,newPath(otherArgs[0]));

FileOutputFormat.setOutputPath(job,newPath(otherArgs[1]));

System.exit(job.waitForCompletion(true) ? 0 : 1);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值