用于处理具有子组的表的SQL查询

时间:2014-09-16 17:01:39

标签: sql oracle

我有一个大型Oracle数据库表,其中包含近2亿行。它只有三列:订户ID字段,日期字段和商品ID字段。

对于此表中的每一行,我需要查找该行是否在表中有任何对应的行,以便:

1)他们属于同一个订阅者(相同的订阅者ID)

2)它们是从当前行开始的某个距离(例如,如果我们当前行是A,则具有相同订阅者ID的行B应该具有A.date> ; B.date> = A.date - 30(天))

3)除了2)我们还必须查询特定的商品ID:(A.date> B.date> = A.date - 30和B. offerid == some_id)

我知道Oracle Analytics功能滞后和领先,我打算将它们用于此目的。根据某些给定字段,这些函数返回有序表上当前行上方或下方字段的值。令人不安的是,具有相同订户ID字段的行数最多变为84.当我在(SUBSCRIBER_ID,DATE)上使用带延迟函数的ORDER BY语句时,对于每一行,我需要检查上面的84行当前行,以确保上面的行与当前行共享相同的SUBSCRIBER_ID。由于一些订户ID子组仅具有3-4行的条目,因此这种不必要的行访问量是浪费的。

如何完成这项工作,而不需要每行检查84行? Oracle是否支持任何仅适用于GROUP BY语句生成的子组的方法?

2 个答案:

答案 0 :(得分:0)

一种选择是使用这样的自联接:

SELECT t1.*, NVL2(t2.subscriber_id, 'Yes', 'No') as match_found
FROM
  myTable t1 LEFT JOIN 
  myTable t2 ON t1.subscriber_id = t2.subscriber_id 
              AND t1.date > t2.date AND t2.date >= t1.date - 30
              AND t2.offerid = <filter_offer_id>

答案 1 :(得分:0)

实际上,Oracle中的分析函数COUNT(*)为我做了必要的事情。我使用了以下结构

SELECT
SUBSCRIBER_ID,
SEGMENTATION_DATE,
OFFER_ID,
COUNT(*) OVER (PARTITION BY SUBSCRIBER_ID ORDER BY SEGMENTATION_DATE RANGE BETWEEN UNBOUNDED     PRECEDING AND 1 PRECEDING) AS SENDEVER,
COUNT(*) OVER (PARTITION BY SUBSCRIBER_ID ORDER BY SEGMENTATION_DATE RANGE BETWEEN 30 PRECEDING AND 1 
COUNT(CASE WHEN (OFFER_ID =580169) THEN 1 ELSE NULL END ) OVER (PARTITION BY SUBSCRIBER_ID ORDER    BY SEGMENTATION_DATE RANGE BETWEEN 180 PRECEDING AND 1 PRECEDING) AS SEND6M580169
FROM myTable

PARTITION BY根据SUBSCRIBER_ID字段对表进行分组,并在每个组的行上使用适当的RANGE BETWEEN语句,我只选择在所需时间间隔内具有适当日期的语句。

通过在OFFER_ID字段上使用CASE WHEN语句,我进一步过滤当前SUBSCRIBER_ID组中的行,并抛弃所有具有无效商品ID的行。

好消息是这里不需要自我连接,减少了操作的顺序。