MapReduce编程-自连接

来源:互联网 发布:mac zip 打不开 编辑:程序博客网 时间:2024/05/22 12:15

SQL自连接

SQL自身连接,可以解决很多问题。下面举的一个例子,就是使用了SQL自身连接,它解决了列与列之间的逻辑关系问题,准确的讲是列与列之间的层次关系。

对于下面的表cp(存储的孩子和父母的关系),用一个SQL,找出所有的 grandchild 和 grandparent,就是找出所有的 孙子 -> 祖父母

+-------+--------+| child | parent |+-------+--------+| tom   | jack   || hello | jack   || tom   | tong   || jack  | gao    || tom   | jack   || hello | jack   || tong  | haha   |+-------+--------+

可用如下SQL

select t1.child,t2.parent from cp t1,cp t2 where t1.parent = t2.child;

结果如下:

+-------+--------+| child | parent |+-------+--------+| tom   | gao    || hello | gao    || tom   | haha   |+-------+--------+

MapReduce编程实现

上面的SQL其实是做了一个笛卡尔积,怎么用MR算法来实现呢?

使用连接列作为key来实现相等匹配。需要让map的输出能包含左右两张表(t1,t2)的信息。

对于如下的输入文件:

Tom LucyTom JackJone LucyJone JackLucy MaryLucy BenJack AliceJack JesseTerry Tom

map的输出是:

Tom parent_LucyLucy child_TomTom parent_JackJack child_Tom.....

其实就是每条记录都重复两次,来表示两张表。

map函数如下:

public void map(Object key, Text value, Context context)throws IOException, InterruptedException {String strs[] = value.toString().split(" ");if (strs.length == 2) {context.write(new Text(strs[0]), new Text("parent_" + strs[1]));context.write(new Text(strs[1]), new Text("child_" + strs[0]));}}


reduce函数:

public void reduce(Text text, Iterable<Text> values, Context context)throws IOException, InterruptedException {List<Text> grandchilds = new ArrayList<Text>();List<Text> grandparents = new ArrayList<Text>();for (Text name : values) {if (name.toString().trim().startsWith("child_")) {grandchilds.add(new Text(name.toString().substring(6)));} else if (name.toString().trim().startsWith("parent_")) {grandparents.add(new Text(name.toString().substring(7)));}}for (Text gchild : grandchilds) {for (Text gparent : grandparents) {context.write(gchild, gparent);}}}}

输出结果为:

JoneJesse
Jone Alice
Tom Jesse
Tom Alice
Tom Ben
Tom Mary
Jone Ben
Jone Mary
Terry Jack
Terry Lucy

0 0