按日期过滤大表

时间:2015-07-21 15:47:10

标签: sql performance date join hive

我有一个表VISIT_INFO,包含以下列:

pers_key - unique identifyer for each person
pers_name - name of person
visit_date - date at which they visited a business

另一个表VALID_DATES,包含以下列:

condition - string
start_date - date
end_date - date 

我目前有以下查询:

select pers_key, pers_name from VISIT_INFO a
CROSS JOIN
(select start_date, end_date from VALID_DATES where condition = 'condition1') b
WHERE (a.visit_date >= b.start_date and a.visit_date <= b.end_date)
GROUP BY a.pers_key

所以&#39; condition1&#39;有一个特定的start_date和end_date。我需要为两个日期之间的访问过滤VISIT_INFO。我想知道是否有更有效的方法来做到这一点。根据我目前的理解,它目前必须遍历整个表(数百万行)并将start_date和end_date添加到每一行。那么它是否必须再次遍历每一行并测试WHERE条件?

我问这个是因为当我删除交叉连接并对condition1硬编码start_date和end_date时,它花费的时间要少得多。我试图在日期中避免硬编码,因为这将导致严重的单调乏味。

重申一下,有没有更好的方法来过滤VALIS_DATES中特定日期的VISIT_INFO?

编辑:我刚刚意识到我遗漏了一条相当大的信息,因为这都属于HIVE。所以EXISTS和加入(在b和c之间)是不可能的。

3 个答案:

答案 0 :(得分:1)

怎么样:

SELECT DISTINCT pers_key, pers_name
FROM visit_info
WHERE EXISTS
(
    SELECT 1
    FROM valid_dates
    WHERE condition = 'condition1'
    AND visit_date BETWEEN start_date AND end_date
);

答案 1 :(得分:0)

with dt as (select start_date, end_date from VALID_DATES where condition = 'condition1')
select a.pers_key, a.pers_name 
from VISIT_INFO a
JOIN dt on a.visit_date between dt.start_date and dt.end_date
GROUP BY a.pers_key

答案 2 :(得分:0)

尝试exists版本绝对是可能的。但是,您可能最好扩展VALID_DATES表,因此每个日期有一行。

然后,查询:

select vi.*
from VISIT_INFO vi JOIN
     VALID_DATES_expanded vde
     ON vi.visit_date = vde.valid_date
where vde.condition = 'condition1';

可以使用VISIT_INFO(visit_date)VALID_DATES_expanded(condition, valid_date)上的索引。如果VISIT_INFO非常大且查询选择了相对较少的行,这可能是解决此问题的最快方法。