views:

60

answers:

1

My ERP system has a half baked deletion tracking system which inserts the following info into a table called M2MDeleteLog. I have left out unnecessary columns such as RecordId for simplicity.

    LogDate           Workstation     LogInfo
    1/7/2010 11:01:51   TECH-M2MTEST    Deleting 1 Rows From SOMast
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOMAST from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Deleting 1 Rows From SOItem
    1/7/2010 11:01:51   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:01:51   TECH-M2MTEST    Deleting 1 Rows From SOItem
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOMAST from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Deleting 1 Rows From SOMast
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Deleting 1 Rows From SOItem
    1/7/2010 11:01:00   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:01:00   TECH-M2MTEST    Deleting 1 Rows From SOItem
    1/7/2010 11:00:29   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOMAST from form frmSo Parameters: NONE
    1/7/2010 11:00:29   TECH-M2MTEST    Deleting 1 Rows From SOMast
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SODBOM from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SORELS from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Deleting 1 Rows From SOItem
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Unqualified M2MDELETE by D.STEIN in SOITEM from form frmSo Parameters: NONE
    1/7/2010 11:00:28   TECH-M2MTEST    Deleting 1 Rows From SOItem

Unfortunately, most of the pertinent information is in 1 text field. The first step is to pull the user (D.STEIN), screen (SOMAST), and screen (frmso) from the LogInfo field. That part is relatively easy.

What I want to do is to create a scheduled job, which runs every 15 minutes or so, to look for suspicious activity. I would define suspicious activity as being 3 deletions in a 15 minute interval per user.

But wait! There's More!

In the data I provided, there are only 3 deletion events, each spaced less than a minute apart. I would define a new deletion event being at least 20 seconds after the last one.

How can I evaluate the LogDate, going back 15 minutes, counting the deletion events per user, so I can notify the admin when more than 3 are recorded for a certain user?

+1  A: 

EDIT: ah, shoot, I just noticed the SQL2K tag. Example 1 should still work, but example 2 will not. Hmm, how could we remedy this.....?

EDIT: fixed!

EDIT: even better!

Asuming you have parsed the text field, this query will give you any deletion that was preceded by at least 2 deletions by the same user in a 15 minute window:

SELECT UserName, LogDate
FROM #parsed_data a
WHERE EXISTS (
  SELECT * FROM #parsed_data b
  WHERE a.UserName = b.UserName
    AND b.LogDate < a.LogDate
    AND DATEDIFF(MINUTE,b.LogDate,a.LogDate) <= 15
  HAVING COUNT(*) >= 2
  )

(You should have an index on (UserName LogDate), btw)

As far as only counting deletes spaced apart by 20 seconds or more, that's not so simple. Something like this perhaps?

SQL2K, based on this by Quassnoi:

SELECT a.UserName, a.LogDate, b.LogDate, c.LogDate --, etc
FROM #parsed_data a
JOIN #parsed_data b 
  ON b.RecordId = (
    SELECT TOP 1 b0.RecordId FROM #parsed_data b0
    WHERE b0.UserName = a.UserName AND b0.LogDate < a.LogDate1
      AND DATEDIFF(MINUTE,b0.LogDate,a.LogDate) <= 15
      AND DATEDIFF(SECOND,b0.LogDate,a.LogDate) >= 20
    ORDER BY b0.LogDate DESC
    )
JOIN #parsed_data c
  ON c.RecordId = (
    SELECT TOP 1 c0.RecordId FROM #parsed_data c0
    WHERE c0.UserName = b.UserName AND c0.LogDate < b.LogDate
      AND DATEDIFF(MINUTE,c0.LogDate,a.LogDate) <= 15
      AND DATEDIFF(SECOND,c0.LogDate,b.LogDate) >= 20
    ORDER BY c0.LogDate DESC
    )

SQL2005/2008, CROSS APPLY:

SELECT a.UserName
, a.LogDate AS LogDate0 -- current
, b.LogDate AS LogDate1 -- prior
, c.LogDate as LogDate2 -- prior prior
FROM #parsed_data a
CROSS APPLY (
  SELECT TOP 1 b.LogDate FROM #parsed_data b 
  WHERE b.UserName = a.UserName
    AND b.LogDate < a.LogDate
    AND DATEDIFF(MINUTE,b.LogDate,a.LogDate) <= 15
    AND DATEDIFF(SECOND,b.LogDate,a.LogDate) >= 20
  ORDER BY b.LogDate DESC
  ) b
CROSS APPLY (
  SELECT TOP 1 c.LogDate FROM #parsed_data c
  WHERE c.UserName = a.UserName
    AND c.LogDate < b.LogDate
    AND DATEDIFF(MINUTE,c.LogDate,a.LogDate) <= 15
    AND DATEDIFF(SECOND,c.LogDate,b.LogDate) >= 20
  ORDER BY c.LogDate DESC
  ) c

In the CROSS APPLY, I used TOP 1 LogDate...ORDER BY LogDate DESC rather than MAX(LogDate) so you can add other fields to the result set, like RecordId, Workstation, etc.

Peter