Hive不支持非equi连接:常见的解决方法是将连接条件移动到where子句,当您需要内部连接时,该子句可以正常工作。但是左边的连接呢?
受挫的例子。假设我们有一个orderLineItem表,我们需要加入一个具有productID,price&的ProductPrice表。适用价格的日期范围。我们想加入到ProductID = ProductID&开始日期和结束日期之间的OrderDate。如果productID或有效日期范围不匹配,我仍然希望查看所有orderLineItems。
这个SQL小提琴是我们如何在MSSQL中执行此操作的示例: http://sqlfiddle.com/#!6/fb877/7
问题 如果我应用典型的解决方法,并将非equi过滤器移动到where子句,它将成为内部联接。在上面的例子中,在sql小提琴&下面,我有一个不在查找中的产品ID。
问题: 如果蜂巢不支持非eqi-joins,如何实现左非eqi?
[SQLFiddle Content]
表:
CREATE TABLE OrderLineItem(
LineItemIDId int IDENTITY(1,1),
OrderID int NOT NULL,
ProductID int NOT NULL,
OrderDate Date
);
CREATE TABLE ProductPrice(
ProductID int,
Cost float,
startDate Date,
EndDate Date
);
加载数据&我们如何加入MSSQL:
--Old Price. Should be ignored
INSERT INTO ProductPrice(ProductID, COST,startDate,EndDate) VALUES (1, 50,'12/1/2012','1/1/2013');
INSERT INTO ProductPrice(ProductID, COST,startDate,EndDate) VALUES (2, 55,'12/1/2012','1/1/2013');
--Price for Order 2. Should be applied to Order 1
INSERT INTO ProductPrice (ProductID, COST,startDate,EndDate) VALUES(1, 20,'12/1/2013','1/1/2014');
INSERT INTO ProductPrice (ProductID, COST,startDate,EndDate) VALUES(2, 25,'12/1/2013','1/1/2014');
--Price for Order 2. Should be applied to Order 2
INSERT INTO ProductPrice (ProductID, COST,startDate,EndDate) VALUES(1, 15,'1/2/2014','3/1/2014');
INSERT INTO ProductPrice (ProductID, COST,startDate,EndDate) VALUES(2, 20,'1/2/2014','3/1/2014');
--January 1st 2014 Order
INSERT INTO OrderLineItem(OrderID,ProductID,OrderDate) VALUES (1, 1,'1/1/2014') ;
INSERT INTO OrderLineItem(OrderID,ProductID,OrderDate) VALUES (1, 2,'1/1/2014');
--Feb 1st 2014 Order
INSERT INTO OrderLineItem(OrderID,ProductID,OrderDate) VALUES (2, 1,'2/1/2014');
INSERT INTO OrderLineItem (OrderID,ProductID,OrderDate) VALUES(2, 2,'2/1/2014');
INSERT INTO OrderLineItem (OrderID,ProductID,OrderDate) VALUES(2, 3,'2/1/2014'); -- no price
SELECT * FROM OrderLineItem;
SELECT * FROM OrderLineItem li LEFT OUTER JOIN ProductPrice p on
p.ProductID=li.ProductID AND OrderDate BETWEEN startDate AND EndDate;
答案 0 :(得分:1)
使用添加的序列行号创建左表的副本:
CREATE TABLE OrderLineItem_serial AS
SELECT ROW_NUMBER() OVER() AS serial, * FROM OrderLineItem;
备注:这可能对某些表格格式更好(必须没有压缩):
CONCAT(INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE) AS serial
进行内部联接:
CREATE TABLE OrderLineItem_inner AS
SELECT * FROM OrderLineItem_serial li JOIN ProductPrice p
on p.ProductID = li.ProductID WHERE OrderDate BETWEEN startDate AND EndDate;
左连接序列号:
SELECT * FROM OrderLineItem_serial li
LEFT OUTER JOIN OrderLineItem_inner i on li.serial = i.serial;
答案 1 :(得分:1)
为什么不单独使用允许NULL情况的WHERE子句?
SELECT * FROM OrderLineItem li
LEFT OUTER JOIN ProductPrice p
ON p.ProductID=li.ProductID
WHERE ( StartDate IS NULL OR OrderDate BETWEEN startDate AND EndDate);
这应该照顾它 - 如果左连接匹配它' ll将使用日期逻辑,如果它没有保持NULL值完整,因为左连接应该。
答案 2 :(得分:0)
不确定是否可以避免使用双重联接:
SELECT *
FROM OrderLineItem li
LEFT OUTER JOIN (
SELECT p.*
FROM ProductPrice p
JOIN OrderLineItem li
ON p.ProductID=li.ProductID
WHERE OrderDate BETWEEN StartDate AND EndDate ) p
ON p.ProductId = li.ProductID
WHERE StartDate IS NULL OR
OrderDate BETWEEN StartDate AND EndDate;
这样,如果存在匹配项且StartDate不为null,则必须有一个有效的开始/结束日期匹配项。
答案 3 :(得分:-2)
Hive 0.10支持交叉连接,因此您可以处理所有" theta join" WHERE子句中的(非等值)条件。