Reputation: 71
I have a table named Logs
:
->OCCUR_TIME --date and time
->NAME --name of a person
->KIND --the kind of log (eg. 40 means `something`)
->VALUE --the value of the kind of log (eg. 99)
I have to create a query:
SELECT
*
FROM LOGS
WHERE NAME='dude'
ORDER BY KIND, OCCUR_TIME, VALUE;
Now this displays the logs and sorted by kind, then occur time (if occur_time is exactly the same it will then sort by value).
Notes:
What if for an example there was a problem with the log and after the VALUE 400 the next VALUE is 398?
Example:
Occur_Time | Name | Kind | Value
2012-06-26 15:14:25.407 dude 40 398
2012-06-27 16:55:28.730 dude 40 399
2012-06-30 02:43:26.763 dude 40 400
2012-06-30 05:26:32.673 dude 40 398 <-- data prob. (possible rollback)
2012-06-30 16:35:28.330 dude 40 399 <-- problem continuing
2012-06-20 20:29:51.207 dude 41 100 <-- no prob. bcoz its another kind
2012-06-23 05:50:59.130 guy 40 500 <-- no prob. bcoz its another name
I want a query that will find the problem, and where it started. Like this?
Please help. Thank you.
Upvotes: 0
Views: 59
Reputation: 1270653
In SQL Server 2012, you would do this using the lag() function.
I'll assume you are using an earlier version, but post 2005. You can do this with nested windows functions.
select name, KIND, OCCUR_TIME, VALUE,
(case when max(testval) over (partition by kind, name) <> min(testval) over (partition by kind)
then 'FAIL'
else 'OKAY'
end) as status
from (SELECT *,
row_number() over (partition by kind, name order by occur_time, value) as seqnum,
(value - row_number() over (partition by kind, name order by occur_time, value)) as testval
FROM LOGS
WHERE NAME='dude'
) t
ORDER BY name, KIND, OCCUR_TIME, VALUE
The idea is to use row_number() to generate a sequence of numbers. The difference between the value and the sequence should be a constant. The outer query looks at the min and max values of these. If they are different, you have a problem.
Upvotes: 0
Reputation: 30912
Not an ideal query, but this will list the problems:
select l1.*, l2.*
from logs l1 -- self join on the columns that are the same
inner join logs l2 on l1.Name = l2.Name and l1.Kind = l2.kind
where l1.occur_time > l2.occur_time
and l1.value < l2.value
Basically this will find all mismatches, where the time grows, but the value diminishes. It will return a lot of duplicates for every occurence, though, so you might have to restrict with something like this:
select distinct l1.Name, l1.Kind
from logs l1 -- self join on the columns that are the same
inner join logs l2 on l1.Name = l2.Name and l1.Kind = l2.kind
where l1.occur_time > l2.occur_time
and l1.value < l2.value
to isolate the problematic Name/Kind pairs
Upvotes: 1