SQL - 如果在过去一小时内插入了新的唯一记录,则发出警报

时间:2012-06-07 12:40:10

标签: sql sql-server-2005

我正在尝试以SQL查询的形式找到针对以下问题的优雅解决方案。

新记录将插入Log表中。 我需要检测我之前没见过的任何新记录(在最后一小时内插入)并生成警报(例如,这些记录的数量> 0)

ID, Url, DOB
1, site1.com/page1, "5/06/2012 20:01"
2, site2.com/page2, "5/06/2012 21:20"
3, site1.com/page1, "6/06/2012 10:05"

如果“now”是6/06/2012 10:40 - 我看到插入了1条新记录(id = 3),但我不想生成警报,因为我们之前已经看过这个URL(id = 1)。

如果有的话 4,site3.com / pageX,“6/06/2012 10:08” 然后我想生成一个警报(返回计数= 1),因为这行是在最后一小时插入的,我们之前没有看到它。

实施它的最佳方法是什么?理想情况下没有嵌套查询

5 个答案:

答案 0 :(得分:5)

我认为这就是你所追求的。这将在最后一小时检索新条目(其中new表示最后一小时没有访问过相同的URL)

SELECT  *
FROM    Log
WHERE   DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
AND     NOT EXISTS
        (   SELECT  1
            FROM    Log T1
            WHERE   T1.URL = Log.URL 
            AND     T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
        )

SQL Fiddle

上的工作示例

修改

刚看到你只需要一个计数的评论:

SELECT  COUNT(*)
FROM    Log
WHERE   DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
AND     NOT EXISTS
        (   SELECT  1
            FROM    Log T1
            WHERE   T1.URL = Log.URL 
            AND     T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP)
        )

编辑2

我不确定为什么只需要一个选择,但是,最接近一个选择的是:

SELECT  COUNT(*)
FROM    (   SELECT  *, MIN(DOB) OVER(PARTITION BY URL) [FirstViewed]
            FROM    Log
        ) Log
WHERE   FirstViewed >= DATEADD(HOUR, -1, CURRENT_TIMESTAMP)

如果在过去一小时内访问过两次同一页面,则仍会返回2。

http://sqlfiddle.com/#!3/5a8bc/1

答案 1 :(得分:2)

这个做了另类选择,首先通过分组搜索唯一网址,然后在最后一小时提取这些网址。

SELECT x1.*
FROM
  (SELECT URL,
          COUNT(ID) AS urlcount,
          MAX(DOB) AS uniqueurl
   FROM Log
   GROUP BY URL HAVING count(ID) = 1
   OR MIN(DOB) > dateadd(HOUR ,-1 , CURRENT_TIMESTAMP)) AS x1
WHERE x1.uniqueurl > dateadd(HOUR ,-1 , CURRENT_TIMESTAMP);

http://sqlfiddle.com/#!3/250e0/45/0

我无法弄清楚这是否具有可接受的性能而没有查看解释,但我认为该组中涉及的排序操作可能是一个瓶颈

答案 2 :(得分:1)

没有嵌套查询(SQLFiddle):

SELECT COUNT(DISTINCT T0.URL) 
FROM Log AS T0 
LEFT OUTER JOIN Log AS T1 ON 
    T1.URL = T0.URL 
    AND T1.DOB < DATEADD(HOUR, -1, CURRENT_TIMESTAMP) 
WHERE 
    T0.DOB > DATEADD(HOUR, -1, CURRENT_TIMESTAMP) 
    AND T1.ID IS NULL

但它确实与GarethD的解决方案相同,性能明智。

答案 3 :(得分:0)

试试这个:

SELECT DISTINCT a.id, a.url, a.dob
FROM Log a JOIN Log b ON (a.url = b.url)
WHERE UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(a.DOB)<=3600 
  AND UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(b.DOB)>3600;

它应该返回遵循您在问题中指定的模式的所有记录。

观察我使用UNIX_TIMESTAMP将日期转换为秒,因此减法将返回时间差,表示为秒数。并且必须在3600秒内进行比较。

编辑

该句已得到纠正。但这是针对MySQL的(我没有看到sql-server2005标签)

答案 4 :(得分:-1)

select distinct(a.url) from tbl a, tbl b where a.dob>(now-hour) and b.dob<=(now-hour) and a.url=b.url; 

(用你选择的数据库替换时间操作。索引urls和dob)

同样希望您的数据库足够明智,可以在使用索引进行连接和连接之前进行dob比较。