在Hive中,我有两个表,如下所示:
SELECT * FROM p_test;
OK
p_test.id p_test.age
01 1
02 2
01 10
02 11
Time taken: 0.07 seconds, Fetched: 4 row(s)
SELECT * FROM p_test2;
OK
p_test2.id p_test2.height
02 172
01 170
Time taken: 0.053 seconds, Fetched: 2 row(s)
我应该在p_test表中得到同一用户之间的年龄差异。因此,我通过 row_number 函数运行HiveQL,如下所示:
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER(partition by id order by age asc) rn FROM p_test) t1
LEFT JOIN
(SELECT *, ROW_NUMBER() OVER(partition by id order by age asc) rn FROM p_test) t2
ON t2.id=t1.id AND t1.rn=(t2.rn+1)
LEFT JOIN
(SELECT * FROM p_test2) t_2
ON t_2.id = t1.id;
其结果是:
t1.id t1.age t1.rn t2.id t2.age t2.rn t_2.id t_2.height
01 1 1 NULL NULL NULL 01 170
01 10 2 01 1 1 01 170
02 11 1 NULL NULL NULL 02 172
02 2 2 02 11 1 02 172
Time taken: 60.773 seconds, Fetched: 4 row(s)
到目前为止还可以。但是,如果我将左连接表 t1 和表 t2 的条件移到最后一行,如下所示:
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER(partition by id order by age asc) rn FROM p_test) t1
LEFT JOIN
(SELECT *, ROW_NUMBER() OVER(partition by id order by age asc) rn FROM p_test) t2
LEFT JOIN
(SELECT * FROM p_test2) t_2
ON t_2.id = t1.id
AND t2.id=t1.id AND t1.rn=(t2.rn+1);
我得到了以下意外结果:
t1.id t1.age t1.rn t2.id t2.age t2.rn t_2.id t_2.height
01 1 1 01 1 1 NULL NULL
01 1 1 01 10 2 NULL NULL
01 1 1 02 11 1 NULL NULL
01 1 1 02 2 2 NULL NULL
01 10 2 01 1 1 01 170
01 10 2 01 10 2 NULL NULL
01 10 2 02 11 1 NULL NULL
01 10 2 02 2 2 NULL NULL
02 11 1 01 1 1 NULL NULL
02 11 1 01 10 2 NULL NULL
02 11 1 02 11 1 NULL NULL
02 11 1 02 2 2 NULL NULL
02 2 2 01 1 1 NULL NULL
02 2 2 01 10 2 NULL NULL
02 2 2 02 11 1 02 172
02 2 2 02 2 2 NULL NULL
似乎我移至最后一行的条件不再起作用。困扰了我好久。希望我能听到任何有价值的答案,对于任何事先为我提供答案的人来说都是如此。
答案 0 :(得分:0)
在第二个查询LEFT JOIN
中,将t2设为不具有ON条件将转换为CROSS JOIN
。这就是为什么您有重复的原因。对于id = 01,您在子查询t1中有两行,而在t2中最初有2行,此CROSS联接为您提供2x2 = 4行。
ON条件起作用,但是它仅适用于使用t_2子查询的最后一个LEFT连接,仅检查此条件以确定最后一次连接中要联接的行,而不是所有联接,它不影响第一个CROSS联接(左联接,不带ON条件)。
除交叉联接外,每个联接都应具有自己的ON条件。
另请参阅有关无ON条件行为的联接的以下答案:https://stackoverflow.com/a/46843832/2700344
顺便说一句,您无需使用t2联接就可以完全使用滞后或超前分析功能来计算按年龄排序的值。
赞:
lag(height) over(partition by id order by age)
-获取以前的高度