hive/sql-left-join和fallback

ercv8c1e  于 2021-06-02  发布在  Hadoop
关注(0)|答案(2)|浏览(474)

在apache配置单元中,我必须创建我想要左连接的表,保留左数据中的所有数据,并尽可能从右表中添加数据。为此,我使用了两个联接,因为联接基于两个字段(material\u id和location\u id)。这在两个传统的左联接中运行良好:

SELECT 
   a.*, 
   b.*
FROM a
INNER JOIN (some more complex select) b
   ON a.material_id=b.material_id 
   AND a.location_id=b.location_id;

对于位置\u id,数据库只包含两个不同的值,例如1和2。
我们现在有一个要求,如果没有“完美匹配”,这意味着只有material\u id可以连接,并且对于b表中location\u id的连接,没有material\u id和location\u id的正确组合(例如material\u id=100和location\u id=1),连接应该“默认”或“回退”到位置id的其他可能值,例如material id=001和location id=2,反之亦然。这只适用于位置标识。
我们已经研究了所有可能的答案,也有案例等,但没有胜诉。像这样的设置

...
ON a.material_id=b.material_id AND a.location_id=
CASE WHEN a.location_id = b.location_id THEN b.location_id ELSE ...;

我们尝试过或者没有弄清楚如何使用配置单元查询语言。
谢谢你的帮助!也许有人有个聪明的主意。
以下是一些示例数据:

Table a
| material_id | location_id | other_column_a |
| 100         | 1           | 45            |
| 101         | 1           | 45            |
| 103         | 1           | 45            |
| 103         | 2           | 45            |

Table b
| material_id | location_id | other_column_b |
| 100         | 1           | 66            |
| 102         | 1           | 76            |
| 103         | 2           | 88            |

Left - Join Table
| material_id | location_id | other_column_a | other_column_b
| 100         | 1           | 45            | 66
| 101         | 1           | 45            | NULL (mat. not in b)
| 103         | 1           | 45            | DEFAULT TO where location_id=2 (88)
| 103         | 2           | 45            | 88

ps:正如这里所说的存在等不工作的子查询上。

gr8qqesn

gr8qqesn1#

解决方法是左连接而不使用 a.location_id = b.location_id 并按优先顺序对所有行进行编号。然后按行号过滤。在下面的代码中,联接将首先复制行,因为所有匹配的material\u id都将联接,然后 row_number() 函数将为其中的行分配1 a.location_id = b.location_id 两排到哪里 a.location_id <> b.location_id 如果还存在行,其中 a.location_id = b.location_id 如果不存在,则为1。 b.location_id 添加到 order by 在row\u number()函数中,以便它“首选”具有较低 b.location_id 以防没有精确匹配。我希望你已经明白了这个想法。

select * from 
(
SELECT 
   a.*, 
   b.*,
   row_number() over(partition by material_id 
                     order by CASE WHEN a.location_id = b.location_id THEN 1 ELSE 2 END, b.location_id ) as rn
FROM a
LEFT JOIN (some more complex select) b
   ON a.material_id=b.material_id 
)s 
where rn=1
;
sqyvllje

sqyvllje2#

也许这对将来的某个人有帮助:
我们也提出了不同的方法。
首先,我们创建另一个表,根据表b中所有的物料id计算平均值(!)位置。
其次,在联接表中,我们创建了三列:c1—material\u id和location\u id匹配的值(表a与表b左联接的结果)。如果没有完全匹配,则此列为空。
c2-表中的值,在该表中,我们为该物料标识写入平均值(回退)表中的数字(不考虑位置)
c3-实际值列,我们使用case语句来确定当第1列为空时(材料和位置不完全匹配),然后使用第2列的值(材料所有其他位置的平均值)进行进一步计算。

相关问题