3

我有两个表(一个显示发送给客户的所有程序的记录,另一个显示用户对其执行操作的所有程序的记录)。我的最终目标是计算发送给用户的那些程序中有多少被执行了。我现在有办法做到这一点,但有一个问题。程序可能会在一天内多次发送给用户(我将使用 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
.
.
.
4

2 回答 2

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
                 )

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

于 2013-02-21T15:34:03.287 回答
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 ;
于 2013-02-21T17:07:55.890 回答