Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于处理具有子组的表的SQL查询_Sql_Oracle - Fatal编程技术网

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

用于处理具有子组的表的SQL查询,sql,oracle,Sql,Oracle,我有一个大型Oracle DB表,其中包含近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\u id) 我知道

我有一个大型Oracle DB表,其中包含近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\u id)

我知道Oracle分析功能滞后和领先,我计划为此目的使用它们。这些函数根据某些给定字段返回排序表上当前行上方或下方的字段值。令人不安的是,具有相同订户id字段的行数最多变化84行。当我在(SUBSCRIBER_ID,DATE)上使用带有lag函数的ORDER BY语句时,对于每一行,我需要检查当前行上方的84行,以确保上面的行与我的当前行共享相同的SUBSCRIBER_ID。由于某些订阅服务器id子组只有大约3-4行的条目,因此不必要的行访问量是浪费的


我如何才能完成这项工作,而不需要每次检查84行,每行?Oracle是否支持仅对GROUP by语句生成的子组起作用的任何方法?

一个选项是使用如下自联接:

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>
选择t1.*,NVL2(t2.subscriber\u id,'Yes','No')作为找到的匹配项
从…起
myTable t1左联接
t1.subscriber\u id=t2.subscriber\u id上的myTable t2
和t1.date>t2.date和t2.date>=t1.date-30
和t2.offerid=

实际上,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
根据SUBSCRIBER_ID字段对表进行分组,并在每个组的行上的语句之间使用适当的范围,我只选择在所需时间间隔内具有适当日期的语句

通过在OFFER_ID字段上使用CASE-WHEN语句,我进一步过滤了当前订户_ID组中的行,并抛出了所有带有无效OFFER ID的行

好在这里不需要自连接,从而将操作的顺序降低了一个数量级