SQL根据其他行删除重复的行

时间:2013-02-21 15:29:59

标签: sql oracle duplicates

我有两个表(一个显示发送给客户的所有程序的记录,另一个显示用户采取操作的所有程序的记录)。我的最终目标是计算发送给用户的那些程序中有多少人被采取行动。我现在有办法做到这一点,但有一个问题。可以在一天内将程序多次发送给用户(我将使用20作为示例)。如果用户在24小时内对该程序采取了措施,我不希望它被视为19个未被执行的程序和1个被执行的程序。我希望它计为1作用于0的程序失败。

包含发送给客户的程序的表需要进行过滤,以便发送给客户的每个程序每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
.
.
.

2 个答案:

答案 0 :(得分: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
                 )

日期时间算术取决于数据库,但这适用于其中许多数据库。

答案 1 :(得分: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 ;