我的情况几乎与以下主题中讨论的示例相同。
select data where date is max(date) less than x
我有表格
s_currency
cdate ratio currency
-------------------------------------------------------------------
2017-06-06 00:00:00.0 1 USD
2017-06-05 00:00:00.0 1 USD
2017-06-04 00:00:00.0 1 USD
s_transaction
tdate amount currency
-------------------------------------------------------------------
2017-06-05 00:00:00.0 100 USD
2017-06-08 00:00:00.0 55 USD
2017-06-08 00:00:00.0 55 USD
2017-06-08 00:00:00.0 60 USD
我想要的结果是
tdate amount currency ratio cdate
--------------------------------------------------------------------------
2017-06-05 00:00:00.0 100 USD 1 2017-06-05 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 60 USD 1 2017-06-06 00:00:00.0
其中cdate应基于tdate,即其最新货币日期等于或早于交易日期。
另一篇文章中的解决方案在select子句中使用子查询,但它在Impala中不起作用。我尝试使用CTE并与子查询连接,但它们都没有返回所需的结果。以下是我构建的一些查询及其结果
SELECT tdate, amount, t1.currency, ratio, cdate FROM s_transaction t1 , s_currency t2
WHERE t1.currency = t2.currency AND
t2.cdate = (select max(cdate) from s_currency
where currency = t1.currency and cdate <= t1.tdate);
但这会加入表并返回所有货币的交易少于交易日期,所以我得到了
tdate amount currency ratio cdate
------------------------------------------------------------------------------------------
2017-06-08 00:00:00.0 60 USD 1 2017-06-05 00:00:00.0
2017-06-08 00:00:00.0 60 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 60 USD 1 2017-06-04 00:00:00.0
2017-06-05 00:00:00.0 100 USD 1 2017-06-05 00:00:00.0
2017-06-05 00:00:00.0 100 USD 1 2017-06-04 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-05 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-04 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-05 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-04 00:00:00.0
所以,我摆脱了max(cdate)并使用了限制1的订单,但是Impala抛出了一个错误,即不支持的相关子查询带有LIMIT子句。
我尝试过使用CTE并写了
with lastupdate as (
select t2.currency, ratio, max(cdate) as cdate from s_currency t2 join s_transaction t1
on cdate <= tdate and t2.currency = t1.currency group by t2.currency, ratio limit 1
) select t11.*, lst.ratio, lst.cdate
from s_transaction t11 join lastupdate lst
但是在这里,CTE选择一个值并将其用于所有交易,所以我得到了
tdate amount currency ratio cdate
-------------------------------------------------------------------------------------------
2017-06-05 00:00:00.0 100 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 60 USD 1 2017-06-06 00:00:00.0
2017-06-08 00:00:00.0 55 USD 1 2017-06-06 00:00:00.0
05年6月的交易,应该有一个cdate为05年6月。
我甚至尝试在子查询中使用row_number()函数,但是它无法解析t1.tdate来比较日期的值。
我如何实现我的目标?
答案 0 :(得分:0)
我在mysql db中测试了以下SQL语句,它可以工作。
select tdate,amount,b.currency,ratio,max(cdate) from s_transaction a,s_currency b where a.tdate>=b.cdate group by tdate
答案 1 :(得分:0)
我遇到了类似的问题,因此将其发布在这里以供参考。
SELECT t.* FROM
(
SELECT rank() OVER (ORDER BY cdate DESC) daterank, c1.cdate, t1.*
FROM s_currency c1, s_transaction t1
WHERE c1.currency = t1.currency
AND c1.cdate <= t1.tdate
) t
WHERE t.daterank = 1;
问题是 Impala 不支持 coorelated 子查询中的复杂操作。
来自 Impala 官方网站:https://impala.apache.org/docs/build/html/topics/impala_limit.html & https://impala.apache.org/docs/build/html/topics/impala_subqueries.html
限制
那么什么是相关子查询?
相关子查询将来自外部查询块的一个或多个值与子查询的 WHERE 子句中引用的值进行比较。外部 WHERE 子句评估的每一行都可以使用不同的值集进行评估。这些类型的子查询受限于它们可以在内表和外表的列之间进行的比较类型
我发现在这种情况下,Impala 的窗口函数很有用,特别是使用限制(限制 1)或小于(限制 2)从子查询中获得最大等效的排名
https://impala.apache.org/docs/build/html/topics/impala_analytic_functions.html
答案 2 :(得分:0)
您可以将 CTE 与 Lead 一起使用来创建每个货币比率对其有效的范围,然后在不使用联接中的子查询的情况下加入该范围。我发现它的执行速度比使用排名快得多。
WITH startend as (
SELECT
currency,
ratio,
cdate as starttime,
ISNULL( LEAD(cdate) OVER ( PARTITION BY currency ORDER BY cdate), '9999-12-31') endtime
FROM s_currency)
SELECT
tdate,
amount,
t.currency,
ratio,
c.starttime as cdate
FROM s_transaction t
INNER JOIN startend c
ON t.currency = c.currency
AND tdate >= starttime
AND tdate < endtime
不要忘记将所有连接条件添加到分区子句中。