2013-02-21 57 views
3

我有两个表(一个显示发送给客户的所有程序的记录,另一个显示用户对所有程序执行操作的记录)。我的最终目标是计算发送给用户的这些程序中有多少人受到了处理。我现在有办法做到这一点,但有一个问题。程序可能会在一天内多次发送给用户(我将以20为例)。如果用户在24小时内对该程序采取行动,我不希望它被计为19个没有采取行动的程序和1个被采取行动的程序。我希望它计数为1作用于程序,0失败。SQL根据其他行删除重复行

包含发送给客户的程序的表需要过滤掉,以便发送给客户的每个程序仅在每24小时期间显示一次。

我的解决方案是有一个“窗口”类型的东西,这样一旦程序发送给客户,它就被锁定了24小时,因此它不会出现在我的'发送给客户的程序中'多次查询。

我有这样的一个表:

Customer Time Program 
----------------------------------- 
1   8:05 a 
1   10:30 a 
1   11:30 a 
1   12:30 b 
1   1:25 a 
2   9:38 b 
2   10:38 c 
2   1:36 c 
2   2:40 c 
2   3:41 b 
. 
. 
. 

我希望得到一个表(查询,而不是删除)在一定时间框架内消除每个客户重复的程序(迷惑我知道!)

这里是我想要的(用例如3小时的时间框架):

Customer Time Program 
----------------------------------- 
1   8:05 a 
1   11:30 a 
1   12:30 b 
2   9:38 b 
2   10:38 c 
2   2:40 c 
2   3:41 b 
. 
. 
. 
+1

您使用的是什么RDBMS? – Taryn 2013-02-21 15:31:25

+0

什么样的列是“时间”日期时间,时间戳等?你还使用什么rdbms和版本? – 2013-02-21 15:33:58

+0

“时间”的数据类型是什么?对于任何代码来说,确定'1:36'在*'10:38'之后是非常困难的。甲骨文, – 2013-02-21 15:34:02

回答

2

试试这个:

select * 
from t 
where not exists (select 1 from t t2 
        where t2.customer = t.customer and 
         t2.program = t.program and 
         t2.time - t.time < 3.0/24 and 
         t2.time > t.time 
       ) 

日期时间算术取决于数据库,但这对于其中的很多算法都有效。

+0

这是在正确的方向,但它不会显示想要的结果。 – 2013-02-21 15:36:56

+0

@ypercube。 。 。我假设你指的是问题的“相同程序”部分。我只是在 – 2013-02-21 15:48:25

+0

中加上了这个号码。除此之外,这不是OP想要的。我认为,“滚动窗口”的要求只能通过递归查询来解决。 – 2013-02-21 15:49:37

1

我认为你的意思可以通过递归查询来解决(仅)。这里是一个解决方案:

WITH cte AS 
    (SELECT 
     customer, program, time, 
     ROW_NUMBER() 
      OVER (PARTITION BY customer, program 
        ORDER BY time) 
      AS rn, 
     MIN(time) 
      OVER (PARTITION BY customer, program 
        ORDER BY time 
        RANGE BETWEEN 3.0/24 FOLLOWING 
          AND UNBOUNDED FOLLOWING) 
      AS next_time 
    FROM a 
) 

SELECT 
    customer, time, program 
FROM 
    cte 
START WITH rn = 1 
CONNECT BY PRIOR customer = customer 
     AND PRIOR program = program 
     AND PRIOR next_time = time 
ORDER BY 
    customer, time, program ; 

您也可以替换MIN(time)以上FIRST_VALUE(time)并得到相同的结果。这可能更有效率。

测试在SQL-Fiddle

效率上了一个大表可能不会很好。您可以尝试使用较小的一组数据运行查询。

你至少应该添加这个指标,所以它的索引扫描:

CREATE INDEX ix    -- choose a name for the index 
    ON tableX     -- the table name 
    (customer, program, time) ; 

你也可以跳过最终排序或改变它,所以它更类似于使用的索引:

ORDER BY 
    customer, program, time ;