July 12, 2006 at 10:47 am
Hi all,
I have a taxing question for you
If I have a query that returns me the following (which is a list of all Inspections on a given day), what I would like to be able to do is to calculate the time difference between consecutive records. So for example, if I get the following back...
1) Inspection 1, 1/1/2006 09:00
2) Inspection 1, 1/1/2006 10:05
3) Inspection 1, 1/1/2006 12:10
4) Inspection 1, 1/1/2006 13:15
...what I want, probs as a Calculated column, is
1) Inspection 1, 1/1/2006 09:00, None, as there is nothing before it
2) Inspection 1, 1/1/2006 10:05, 01:05
3) Inspection 1, 1/1/2006 12:10, 02:05
4) Inspection 1, 1/1/2006 13:15, 01:05
... a record always calculates the time difference between itself, and the previous record, apart from when it is the first record in the resultset.
Is this at all possible? As I really don't know where to start.
Thanks
Tryst
July 12, 2006 at 11:16 am
Hope you are using SQL Server 2000. If so here is one of the way to solve ur problem....
declare @test-2 table
(
taskvarchar(30),
datedatetime
)
insert into @test-2 values ('Inspection 1', '1/1/2006 09:00')
insert into @test-2 values ('Inspection 1', '1/1/2006 10:05')
insert into @test-2 values ('Inspection 1', '1/1/2006 12:10')
insert into @test-2 values ('Inspection 1', '1/1/2006 13:15')
select a.task, a.date,
convert(varchar(5), dateadd(mi, isnull((select datediff(mi, MAX(date),a.date) from @test-2 b
where b.Task= a.Task
and b.date < a.date),0), cast('01/01/2006' as datetime)),114) as diff
from @test-2 a
order by date
July 12, 2006 at 3:10 pm
Select T1.Inspection, T1.Log_Date, T1.Log_Date - MAX(T2.Log_Date) as TimeGap
FROM InspectionRecord T1
LEFT JOIN InspectionRecord T2 ON T1.Inspection = T2.Inspection AND T1.Log_Date > T2.Log_Date
GROUP BY T1.Inspection, T1.Log_Date
_____________
Code for TallyGenerator
July 13, 2006 at 2:38 am
Good morning all
Nagabhushanam Ponnapalli - your query works perfectly. But ideally, I'd like to wrap it up in a query without using a temp table - a bit like how Sergiy has done. But if that isn't possible, then I will def use this query.
Sergiy, it seems your query doesn't work when I actually change it to map across to my column names. I just get NULL values un the TimeGap column. The query is as follows...
Select T1.InspectionUID,
T1.Description,
T1.CreatedDate,
T1.CreatedDate - MAX(T2.CreatedDate) as TimeGap
FROM tbl_NSP_Inspection T1
LEFT JOIN tbl_NSP_Inspection T2 ON T1.Description = T2.Description AND T1.CreatedDate > T2.CreatedDate
GROUP BY T1.InspectionUID, T1.Description, T1.CreatedDate
Thanks for the replies.
Tryst
July 13, 2006 at 3:15 am
>Nagabhushanam Ponnapalli - your query works perfectly. But ideally, I'd like to wrap it up in a query without using a temp table - a bit like how Sergiy has done.
The temp table is for test data - not part of the example query.
>Sergiy, it seems your query doesn't work when I actually change it to map across to my column names. I just get NULL values un the TimeGap column.
You would expect to get null values (with meaning: 'not applicable') for the first record in each group. But if you're getting NULLs on every row, it's probably either because:
(a) Description is unique in the table. you should check that this is the correct grouping column. I would expect the grouping to be on a foreign key.
(b) Each group of Inspection records with the same description all have the same CreatedDate.
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
July 13, 2006 at 3:30 am
Hi stax68,
yes it is because the Description column in the table is Unique. Is this the problem then?
Tryst
July 13, 2006 at 3:37 am
Yes. The query is working fine, but every record is in a group of 1. You need to decide what you are grouping on - probably whatever entity it is that gets inspected. Complete the following sentence:
I want to show a list of inspections for each ______
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
July 13, 2006 at 4:18 am
I want to show a list of inspections for each for each day where each Inspection undertaken has a calculated column added to it that determines the time difference between the currect Inspection in question, and the one before it (examples of this are provided in my initial post). But there is an exception where we have the first inspection of the day will not have a duration value (default it to 00:00) as it can't be calulated because it doens't have an Inspection before it on that day.
Hope this has clarified things, if not, let me know.
Thanks
Tryst
July 13, 2006 at 4:31 am
Yes.
I could perhaps have guessed that by rereading your original post, but putting time into speculative answers which are potentially irrelevant is beyond the call of duty as far as I'm concerned! Try this:
(day,0,datediff(day,0,T1.CreatedDate)) InspDate,
tbl_NSP_Inspection T1
join tbl_NSP_Inspection T2
T2.CreatedDate >= dateadd(day,0,datediff(day,0,T1.CreatedDate))
T2.CreatedDate < T1.CreatedDate
by T1.InspectionUID, T1.CreatedDate
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
July 13, 2006 at 7:51 am
Hi All,
Here is a solution that uses a correlated subquery instead of joins.
SELECT
[task]
,[date]
,[date] - (select top 1 [date]
from [test_dt]
where [task] = main.[task]
and [date] < main.[date]
order by [date] desc) as timegap
FROM [test_dt] as main
I haven't compared its performance against the other solutions but I find it easier to read.
Antonio Macedo
July 13, 2006 at 8:13 am
There is a need for the time day as it is used for reporting on. I don't want to write this data into a separate column each time an inspection is undertaken as it is written on a mobile device, so the less amount of trips to the database, the better.
The query worked a treat by the way.
Thanks
Tryst
July 13, 2006 at 8:49 am
Hi All,
I've just compared the performance between the correlated subquery and the left join solutions.
With no index, the left join performs better than correlate subquery.
Correlated Subquery = 75%
Left Join = 25%
With a index on the date field, the correlate subquery performs better than left join.
Correlated Subquery = 38%
Left Join = 62%
Correlate Subquery Solution
SELECT
[task]
,[date]
,[date] - (select top 1 [date]
from [test_dt]
where [task] = main.[task]
and [date] < main.[date]
order by [date] desc) as timegap
FROM [test_dt] as main
Left Join Solution
select T1.task,
T1.date,
T1.date - max(T2.date) TimeGap
from test_dt T1
left join test_dt T2
on T2.date >= dateadd(day,0,datediff(day,0,T1.date))
and T2.date < T1.date
group by T1.task, T1.date
Antonio Macedo
July 13, 2006 at 10:21 am
Those queries aren't equivalent. The column you are calling 'task' is supposed to be unique. So your use of it in the subquery should mean that the query returns no records.
It is true that correleated subqueries sometimes give better performance though, especially when they are of the 'TOP 1' variety.
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
July 13, 2006 at 4:16 pm
Not in this case.
If to make queries identical:
IF Object_ID('[test_dt]') IS NOT NULL
DROP TABLE [test_dt]
CREATE TABLE [test_dt](
Task nvarchar(50),
date datetime)
INSERT INTO [test_dt]
SELECT 'Inspection 1', '2006-07-14 09:00'
UNION
SELECT 'Inspection 2', '2006-07-14 09:15'
UNION
SELECT 'Inspection 4', '2006-07-14 09:50'
UNION
SELECT 'Inspection 3', '2006-07-14 11:20'
UNION
SELECT 'Inspection 6', '2006-07-14 11:23'
UNION
SELECT 'Inspection 10', '2006-07-14 11:39'
UNION
SELECT 'Inspection 7', '2006-07-14 12:30'
UNION
SELECT 'Inspection 5', '2006-07-14 14:22'
CREATE CLUSTERED INDEX T_Date ON [test_dt](date)
CREATE INDEX T_Task ON [test_dt](Task)
SELECT [task]
,[date]
,[date] - (select top 1 [date]
from [test_dt]
where date >= dateadd(day,0,datediff(day, 0, main.date))
and [date] < main.[date]
order by [date] desc) as timegap
FROM [test_dt] as main
--Left Join Solution
select T1.task,
T1.date,
T1.date - max(T2.date) TimeGap
from test_dt T1
left join test_dt T2 on T2.date < T1.date
and T2.date >= dateadd(day,0,datediff(day,0,T1.date))
group by T1.task, T1.date
DROP TABLE [test_dt]
it takes:
Correlated Subquery = 50.09%
Left Join = 49.91%
But my experience does not allow me to trust the numbers from execution plan.
So I put it into real performance test.
DECLARE @I int
SET @I = 1000
WHILE @I > 0
BEGIN
SELECT [task]
,[date]
,[date] - (select top 1 [date]
from [test_dt]
where date >= dateadd(day,0,datediff(day, 0, main.date))
and [date] < main.[date]
order by [date] desc) as timegap
FROM [test_dt] as main
SET @I = @I-1
END
--Left Join Solution
--DECLARE @I int
SET @I = 1000
WHILE @I > 0
BEGIN
select T1.task,
T1.date,
T1.date - max(T2.date) TimeGap
from test_dt T1
left join test_dt T2 on T2.date < T1.date
and T2.date >= dateadd(day,0,datediff(day,0,T1.date))
group by T1.task, T1.date
SET @I = @I-1
END
Result:
Correlated Subquery = 18 sec
Left Join = 12 sec
_____________
Code for TallyGenerator
July 16, 2006 at 4:09 pm
Hi this query was for SQL Server Mobile and it doesn't make use of Sub-queries or TOP -
Thanks
Tryst
Viewing 15 posts - 1 through 15 (of 17 total)
You must be logged in to reply to this topic. Login to reply