场景:有两张表,一张用户表(user),交易表(transactions)。两张表的字段如下:

两份表数据做个左连接,查询出(商品名,地址)这种格式。

这样就是相当于交易表是左表,不管怎么样数据都要保留,然后从右边里面查出来弥补左表。

效果如下:

思路:写两个map,把两个表的数据都读进来,在reduce端进行连接,然后按照格式要求写出去。

(1)map1:读取transaction文件,封装为:


protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, PairOfStrings, PairOfStrings>.Context context)

throws IOException, InterruptedException {

String lines=value.toString();

String[] args=lines.split(" ");

String productID=args[1];

String userID=args[2];

//把outPutKey加了一个2,这么做的目的是,后续在reduce端,聚合时,这个数据能够晚点到达。

outPutKey.set(userID, "2");

outPutValue.set("P", productID);

context.write(outPutKey, outPutValue);

}

(2)map2:读取user文件,封装为:

static class map2 extends Mapper<LongWritable, Text,PairOfStrings,PairOfStrings>

{

PairOfStrings outPutKey=new PairOfStrings();

PairOfStrings outPutvalue=new PairOfStrings();

@Override

protected void map(LongWritable key, Text value,

Mapper<LongWritable, Text, PairOfStrings, PairOfStrings>.Context context)

throws IOException, InterruptedException {

String line=value.toString();

String[] args=line.split(" ");

String userID=args[0];

String locationID=args[1];

//把outPutKey加了一个1,这么做的目的是,后续在reduce端,聚合时,这个数据能够早于transaction文件里面的数据到达。

outPutKey.set(userID, "1");

outPutvalue.set("L", locationID);

context.write(outPutKey, outPutvalue);

}

(3)reduce:把map端的数据要根据用户ID分区,相同的用户ID写入到同一个分区,进而写入到同一个Reduce分区,然后在Reduce中根据PairOfStrings这个类的自己的排序规则对数据排序。因为前面对key做了处理(加了1,2),所以是用户的地址这些信息先到达reduce。,然后根据不同的分组,把数据写出来。






总的代码结构:

LeftCmain:

package com.guigu.left;

import java.io.IOException;
import java.util.Iterator; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.MultipleInputs;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat; import edu.umd.cloud9.io.pair.PairOfStrings; public class LeftCmain { //读取transaction文件
static class map1 extends Mapper<LongWritable, Text, PairOfStrings,PairOfStrings>
{
PairOfStrings outPutKey=new PairOfStrings();
PairOfStrings outPutValue=new PairOfStrings(); @Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, PairOfStrings, PairOfStrings>.Context context)
throws IOException, InterruptedException {
String lines=value.toString();
String[] args=lines.split(" ");
String productID=args[1];
String userID=args[2];
outPutKey.set(userID, "2");
outPutValue.set("P", productID);
context.write(outPutKey, outPutValue);
} } //读取user文件
static class map2 extends Mapper<LongWritable, Text,PairOfStrings,PairOfStrings>
{
PairOfStrings outPutKey=new PairOfStrings();
PairOfStrings outPutvalue=new PairOfStrings();
@Override
protected void map(LongWritable key, Text value,
Mapper<LongWritable, Text, PairOfStrings, PairOfStrings>.Context context)
throws IOException, InterruptedException {
String line=value.toString();
String[] args=line.split(" ");
String userID=args[0];
String locationID=args[1];
outPutKey.set(userID, "1");
outPutvalue.set("L", locationID);
context.write(outPutKey, outPutvalue);
} } /**
* 这个的关键点在于,取出的数据:要求先取出地址的数据。
* @author Sxq
*
*/
static class reduce1 extends Reducer<PairOfStrings, PairOfStrings, Text, Text>
{
Text produceID=new Text();
Text localID=new Text("undefine"); @Override
protected void reduce(PairOfStrings arg0, Iterable<PairOfStrings> Iterator1,
Reducer<PairOfStrings, PairOfStrings, Text, Text>.Context context)
throws IOException, InterruptedException {
Iterator<PairOfStrings> iterator=Iterator1.iterator(); //由于做了二次排序,可以保证先得到的是地址的数据。
if(iterator.hasNext())
{
PairOfStrings fisrPair=iterator.next();
// System.out.println("firstPair="+fisrPair.toString());
//如果是地址的信息,那就把他直接放出来
if(fisrPair.getLeftElement().equals("L"))
{
localID.set(fisrPair.getRightElement());
}
}
while(iterator.hasNext())
{
PairOfStrings pairOfStrings=iterator.next();
//System.out.println(pairOfStrings.toString());
produceID.set(pairOfStrings.getRightElement());
System.out.println("prdouct:"+produceID.toString()+"localId:"+localID.toString());
//System.out.println();
context.write(produceID, localID);
}
}
} public static void main(String[] args) throws Exception { Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
job.setJarByClass(LeftCmain.class); job.setMapperClass(map1.class);
job.setReducerClass(reduce1.class); job.setMapOutputKeyClass(PairOfStrings.class);
job.setMapOutputValueClass(PairOfStrings.class);
job.setOutputValueClass(Text.class);
job.setOutputKeyClass(Text.class);
job.setSortComparatorClass(PairOfStrings.Comparator.class); // 在Reduce端设置分组,使得同一个用户在同一个组,然后做拼接。
job.setGroupingComparatorClass(SecondarySortGroupComparator.class);
// 设置分区
job.setPartitionerClass(SecondarySortParitioner.class);
// job.setOutputFormatClass(SequenceFileOutputFormat.class);
Path transactions=new Path("/Users/mac/Desktop/transactions.txt");
MultipleInputs.addInputPath(job,transactions,TextInputFormat.class,map1.class);
MultipleInputs.addInputPath(job,new Path("/Users/mac/Desktop/user.txt"), TextInputFormat.class,map2.class);
FileOutputFormat.setOutputPath(job, new Path("/Users/mac/Desktop/flowresort"));
boolean result = job.waitForCompletion(true);
System.exit(result ? 0 : 1); } }

SecondarySortGroupComparator:

package com.guigu.left;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator; import com.book.test1.CompositeKey; import edu.umd.cloud9.io.pair.PairOfStrings; /**
* 不同分区的组聚合时,可以按照我们要的顺序来排列
* @author Sxq
*WritableComparator
*/
public class SecondarySortGroupComparator extends WritableComparator { public SecondarySortGroupComparator() {
super(PairOfStrings.class,true);
} @Override
public int compare(WritableComparable a, WritableComparable b) { PairOfStrings v1=(PairOfStrings)a;
PairOfStrings v2=(PairOfStrings)b;
return v1.getLeftElement().compareTo(v2.getLeftElement());
} }

SecondarySortParitioner:

package com.guigu.left;

import org.apache.hadoop.mapreduce.Partitioner;

import edu.umd.cloud9.io.pair.PairOfStrings;
/**
*
* @author Sxq
*
*/
public class SecondarySortParitioner extends Partitioner<PairOfStrings, Object>{ @Override
public int getPartition(PairOfStrings key, Object value, int numPartitions) {
return (key.getLeftElement().hashCode()&Integer.MAX_VALUE)%numPartitions;
} }

运行结果:




05Hadoop-左外连接的更多相关文章

  1. 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接(转)

    1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.     内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 stude ...

  2. 【转】深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接

    [原文]:http://www.jb51.net/article/39432.htm 1.内联接(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.    ...

  3. [原创]java WEB学习笔记91:Hibernate学习之路-- -HQL 迫切左外连接,左外连接,迫切内连接,内连接,关联级别运行时的检索策略 比较。理论,在于理解

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. [原创]java WEB学习笔记88:Hibernate学习之路-- -Hibernate检索策略(立即检索,延迟检索,迫切左外连接检索)

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. MyBatis 内连接association 左外连接collection

    前提条件: 学生表 (多  子表) 年级表(一  主表) 1,第一种情况:先查子表所有 student.sql.xml文件如何配 由于有多表连接,无法把查询结果直接封装成一个实体对象--------& ...

  6. SQL 四种连接:内连接、左外连接、右外连接、全连接--转载

    原文:http://zwdsmileface.iteye.com/blog/2191730 个人理解 内连接(INNER JOIN)(典型的连接运算,使用像   =   或   <>   ...

  7. sql的交叉连接,内连接,左外连接,右外连接,全外连接总结

    实践是最好的检验,一直都对这几个连接查询出来的结果有什么不同不大理解,然后自己放一块查询比较了一下,用结果来说话~ 先建两张表如下: t1: id name age 1 张三 18 2 李四 25 t ...

  8. 在查询用户的权限的时候 使用左外连接 和 access数据库中左外连接

    一般做视图最好是做成左外连接的.而其作用尤其在我们查询用户当前的权限时尤为明显,我们将 权限表即模块表放→角色权限表→角色表→用户角色表→用户表 就这样left outer join 连接起来,这样就 ...

  9. mysql的内连接,外连接(左外连接,右外连接)巩固

    1:mysql的内连接: 内连接(inner join):显示左表以及右表符合连接条件的记录: select a.goods_id,a.goods_name,b.cate_name from tdb_ ...

  10. 内连接、左外连接、右外连接、全外连接、交叉连接(CROSS JOIN)-----小知识解决大数据攻略

    早就听说了内连接与外连接,以前视图中使用过.这次自考也学习了,只是简单理解,现在深入探究学习(由于上篇博客的出现)与实践: 概念 关键字: 左右连接 数据表的连接有: 1.内连接(自然连接): 只有两 ...

随机推荐

  1. Redis初步整理

    1,Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的 ...

  2. python网络编程(六)

    tcp通信模型 tcp服务器 在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下: socket创建一个套接字 bind绑定ip和port listen使套接字变为可以被动链接 accept ...

  3. springboot从入门到精通

    1:安装iDEa 2:安装jdk1.8 安装软件https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133 ...

  4. keras 的svm做分类

    SVC继承了父类BaseSVC SVC类主要方法: ★__init__() 主要参数: C: float参数 默认值为1.0 错误项的惩罚系数.C越大,即对分错样本的惩罚程度越大,因此在训练样本中准确 ...

  5. 关于实现udev/mdev自动挂载与卸载

    在网上有很多关于讲mdev的自动挂载基本上都是一个版本,经过测试自动挂载确实可行,但是关于自动卸载mdev似乎不能很好的支持,经过修改已经可以做到与udev的效果相似.不能在挂载的目录中进行热插拔,否 ...

  6. js顺序播放列表中的音乐

    今天一个朋友问我js顺序播放音乐列表中的音乐的问题,我仔细一想,我也没有做过啊,无从下手啊,怎么办?然后我就上网查了一下audio标签,又百度了js如何顺序播放音乐,结果就找到了解决的办法. audi ...

  7. openstack 之~keystone之网关协议

    第一:静态页面和动态页面 上一篇博客介绍了HTTP后,我们知道一个web server的本质就是 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP ...

  8. poj3009 Curling 2.0(很好的题 DFS)

    https://vjudge.net/problem/POJ-3009 做完这道题,感觉自己对dfs的理解应该又深刻了. 1.一般来说最小步数都用bfs求,但是这题因为状态记录很麻烦,所以可以用dfs ...

  9. 最新版Xamarin Mono For Android、Monotouch 安装、破解(实时同步更新)

    以上链接如不是最新,以官方为主,官方更新地址如下:http://xamarin.com/installer_assets/v3/Mac/Universal/InstallationManifest.x ...

  10. Go语言之高级篇beego框架之日志收集系统

    一.日志收集系统架构设计 图1 图2 二.开发环境 1.安装jdk jdk-8u51-windows-x64.exe 安装目录:C:\Program Files\jdk8 2.安装zookeeper ...