Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Query

Author  Topic 

newty25
Starting Member

21 Posts

Posted - 2002-06-26 : 11:45:46
I have a table full of records with updates. It would act as an employee time card.

So you might have empID, empName, UpdateTime, WorkTime.
and I get updates every 5 minutes.

So the problem is that I need to look at the current WorkTime and the previous WorkTime for every record of each individual employee and determine if there is more than an X hour difference between the two WorkTimes in those two updates.

I don't know if I could solve this problem using Transact-SQL or use a Cursor. Does anyone have suggestions?

newty25

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-06-26 : 11:53:20
More detail is needed here. Post the DDL for the involved tables and describe more fully what you would do with the knowledge of a particular WorkTime time difference (e.g. write it to a table, return it as a rowset, what? )

Jonathan Boott, MCDBA

Edited by - setbasedisthetruepath on 06/26/2002 11:54:16
Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-26 : 15:04:23
Okay, so I decided to write myself a cursor to do this... but the insert statement within the cursor doesn't work.

here is the statement

EXEC ("INSERT INTO tmpDataAnomalies(AC,AC_Number,DEST,ORIG,IGTD, Update_Time, AutoId, DataAnomaly) VALUES('" + @curAC + "', '" + @curACNum + "', '" + @curDest + "', '" + @curOrig + "', '" + @curIGTD + "', '" + @curUpdate_Time + "', 1, 2)")

The errors that I get are
Server: Msg 170, Level 15, State 1, Line 1
Line 1: Incorrect syntax near 'Š'.
Server: Msg 105, Level 15, State 1, Line 1
Unclosed quotation mark before the character string ', 1, 2)'.

???
I have no idea what is going wrong. I have SET QUOTED_IDENTIFIER OFF at the beginning of the sql code. It has to be a problem with the double and single quotes, but I don't know which.

newty25



Go to Top of Page

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-06-26 : 15:08:53
I don't recommend dynamic SQL unless you absolutely have to use it, and I'm not convinced yet that it is required. As I mentioned in my first post, providing descriptive posts with good detail is very important; you still haven't given that so my options in helping you are quite limited.

Having said that, you should always place the dynamic sql into a variable and exec() that variable, because if questions arise it is easy to see its contents through a print statement or the t-sql debugger.

Jonathan Boott, MCDBA
Go to Top of Page

izaltsman
A custom title

1139 Posts

Posted - 2002-06-26 : 15:28:48
Some of your variables probably contain single quotes. If that's the case, you'll need to use the REPLACE function around each of the variables in order to double up those single quotes.



Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-27 : 08:24:41
Okay... here is the DDL for the tmpAnomaly table


CREATE TABLE [tmpDataAnomalies] (
[AC] [varchar] (3) NOT NULL ,
[AC_NUMBER] [varchar] (4) NOT NULL ,
[DEST] [varchar] (4) NOT NULL ,
[ORIG] [varchar] (4) NOT NULL ,
[IGTD] [smalldatetime] NOT NULL ,
[Update_Time] [datetime] NOT NULL ,
[AutoID] [tinyint] NOT NULL ,
[DataAnomaly] [varchar] (50) NULL
)


Here is the table I'm pulling information from...


CREATE TABLE [tmpArrivals] (
[AC] [varchar] (3) NOT NULL ,
[AC_NUMBER] [varchar] (4) NOT NULL ,
[DEST] [varchar] (4) NULL ,
[ORIG] [varchar] (4) NULL ,
[IGTD] [smalldatetime] NOT NULL ,
[ETD] [smalldatetime] NULL ,
[ETA] [smalldatetime] NULL ,
[UPDATE_TIME] [datetime] NULL ,
)


Here is the cursor that I wrote:

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

Declare @curAC AS varchar(5)
Declare @curACNum AS varchar(5)
Declare @curDest AS varchar(5)
Declare @curOrig AS varchar(5)
Declare @curIGTD AS smalldatetime
Declare @curUpdate_Time as datetime
Declare @curETA as datetime
Declare @prevAC AS varchar(5)
Declare @prevACNum AS varchar(5)
Declare @prevDest AS varchar(5)
Declare @prevOrig AS varchar(5)
Declare @prevIGTD AS smalldatetime
Declare @prevUpdate_Time as datetime
Declare @prevETA as datetime
Declare @sql as varchar(255)

Declare Anomalies Cursor
Static
Read_Only
For
SELECT A.AC, A.AC_NUMBER, A.DEST, A.ORIG, A.IGTD, A.UPDATE_TIME, A.ETA
FROM TMPARRIVALS A
ORDER BY A.AC, A.AC_NUMBER, A.ORIG, A.DEST, A.IGTD
--Go

Open Anomalies
FETCH FIRST FROM Anomalies into @curAC, @curACNum, @curDest, @curOrig, @curIGTD, @curUpdate_Time, @curETA
FETCH FIRST FROM Anomalies into @prevAC, @prevACNum, @prevDest, @prevOrig, @prevIGTD, @prevUpdate_Time, @prevETA
While @@Fetch_Status = 0
Begin

IF (@curAC = @prevAC and @curACNum = @prevACNum and @curDest = @prevDest and @curOrig = @prevOrig and @curIGTD = @prevIGTD)
BEGIN
IF DATEDIFF(n,@curETA,@prevETA) > 1200
BEGIN
SELECT @SQL = 'INSERT INTO tmpDataAnomalies(AC,AC_Number,DEST,ORIG,IGTD, Update_Time, AutoId, DataAnomaly) VALUES(@curAC, @curACNum, @curDest, @curOrig, @curIGTD, @curUpdate_Time, 1, 2)'
EXEC (@SQL)
END

END

set @prevAC = @curAC
set @prevACNum = @curACNum
set @prevDest = @curDest
set @prevOrig = @curOrig
set @prevIGTD = @curIGTD
set @prevUpdate_Time = @curUpdate_Time
set @prevETA = @curETA

Fetch Next FROM Anomalies into @curAC, @curACNum, @curDest, @curOrig, @curIGTD, @curUpdate_Time, @curETA

End

Close Anomalies
Deallocate Anomalies

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


Here's the original exec statement that I wrote that returned the errors from the previous posting.


EXEC ("INSERT INTO tmpDataAnomalies(AC,AC_Number,DEST,ORIG,IGTD, Update_Time, AutoId, DataAnomaly) VALUES('" + @curAC + "', '" + @curACNum + "', '" + @curDest + "', '" + @curOrig + "', '" + @curIGTD + "', '" + @curUpdate_Time + "', 1, '2') ")


It seems the exec statement won't work due to a problem with the datetimes in the exec statement. I've tried everything I can think of to make it work... setting the quoting identifiers off/on, hard coding the exec statement, etc. Nothing will work. It does find the anomaly that I'm looking for, but it won't insert it into the database because the exec statement fails. Is there some sort of issue with datetimes in an exec statement that I'm overlooking?

can anyone help???
newty25

Go to Top of Page

MakeYourDaddyProud

184 Posts

Posted - 2002-06-27 : 08:30:09
Is it just me or is topic requiring a horiz scroll????

Oh dear, this is gonne be awhile...

<<monet makes money>>
Go to Top of Page

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2002-06-27 : 08:43:27
OK....

First, I don't think you need to use Dynamic SQL to execute the INSERT inside your CURSOR.

Second, and more importantly, I don't think you need a CURSOR at all. Here is my crack at a set-based method. If I understood the data a bit more, I'm sure it could even be done without the temp table....


select
IDENTITY(int,1,1) as RowNum,
A.AC,
A.AC_NUMBER,
A.DEST,
A.ORIG,
A.IGTD,
A.UPDATE_TIME,
A.ETA
into
#temp
from
TMPARRIVALS A
order by
A.AC,
A.AC_NUMBER,
A.ORIG,
A.DEST,
A.IGTD

insert into tmpDataAnomalies (
AC,
AC_Number,
DEST,
ORIG,
IGTD,
Update_Time,
AutoId,
DataAnomaly )
select
A.AC,
A.AC_NUMBER,
A.DEST,
A.ORIG,
A.IGTD,
A.UPDATE_TIME,
A.ETA
from
#temp A
where
exists (
select 1
from
#temp
where
a.RowNum = RowNum - 1 and
A.AC = AC and
A.AC_NUMBER = AC_NUMBER and
A.DEST = DEST and
A.ORIG = ORIG and
A.IGTD = IGTD and
DATEDIFF(n,A.ETA,ETA) > 1200 )

 


<O>
Go to Top of Page

MakeYourDaddyProud

184 Posts

Posted - 2002-06-27 : 08:53:10
If you made the temp table primary key indexed on RowNum, you don't the correlated boolean subquery, thus...

...
...
select
A.AC,
A.AC_NUMBER,
A.DEST,
A.ORIG,
A.IGTD,
A.UPDATE_TIME,
A.ETA
from
#temp A
join #temp B
on
a.RowNum = b.RowNum - 1 and
A.AC = b.AC and
A.AC_NUMBER = b.AC_NUMBER and
A.DEST = b.DEST and
A.ORIG = b.ORIG and
A.IGTD = b.IGTD and
DATEDIFF(n,A.ETA,b.ETA) > 1200 )

... is a good alternative version.

the original boolean subquery might be required where there is evidence of multiple rows matching returned and you only need to test for 1 row, but that depends on your specific requirements.

HTH

Daniel Small MIAP
www.danielsmall.com


<<monet makes money>>
Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-27 : 09:35:38
Thanks a lot. The set-based approach was right on. The only problem
that I am having is that the identity column is being created before
the ordering, which is not returning the result set I need. I did,
however take out the initial identity declaration, so that I could alter the temp table after it was created with an alter statement.
But since the alter takes so long, the query went on and I received
an error on the column RowNum because it didn't exist in the latter
exists query. Is there something I could do to get RowNum ordered
correctly?

Thanks for the help! I'm so close!
newty25

Go to Top of Page

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2002-06-27 : 10:13:16
newty25, the select into should honor the order by when making the RowNum column. I've done it many times. I could be wrong, but maybe you should check your rowset once more...

2sweet, you are making a lot of assumptions about performance issues involved in indexing the temp table (cost of creating the index vs. benefit of inner join over correlated subquery). If performance is a problem, then we can help newty tune the query further. I chose the correlated subquery because I though it would be easier to understand the nature of building the temp table. Regardless, it will be faster than the iterative solution (CURSOR).

<O>
Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-27 : 10:30:46
Thanks Page and 2Sweet. I did check the rowset, and it didn't
work??? I'm using SQL QA v8. I don't know if that makes a
difference or not. I solved the problem by creating a table and
truncating it after use. I'll need the table at least a dozen times
a day, and it orders no problem now. Thanks for all the help... I
used to think I actually knew something about SQL until yesterday and
today.

newty25

Go to Top of Page

MakeYourDaddyProud

184 Posts

Posted - 2002-06-27 : 10:34:16
Yeah, Page you interpreted it as easier to read, and i agree. But, isn't a keyed self join ALWAYS faster than a correlated boolean subquery lookup? Your thoughts...

Daniel Small MIAP
www.danielsmall.com IT Factoring
Go to Top of Page

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2002-06-27 : 10:43:51
In this situation it would be. With the self join you will have one index scan and one index seek (on rownum - 1). The subquery will do two index scans. However, what is not cut&dry is whether the performance gain of trading a scan for a seek out weights the it of creating the clustered index. It probably will, but IMHO sometimes when helping someone completely change their way of thinking (from iterative to setbased) it is important not to cloud the issues with less important details. You post and comments about optimizing the process are certainly valid, but given the context, I don't think they add much value.

Newty25, I am at a loss as to why your RowNum isn't matching your order by. Can you post the DML to insert some sample data into TMPARRIVALS that demonstrates this?

<O>
Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-28 : 08:11:46
I'm not sure what you mean by

quote:
the DML to insert some sample data


I thought DML was the insert statement from above. Or do you want
sample data... cause I definitely post that.

Here is an example of the temp table not sorting on the insert



Also, the query that you sent looks like it is right on the money, yet it won't get the correct record. It returns the prior record and not the current.

Here is an example of this problem



At a glance it looks correct, it is finding the difference between the current and prior, but the record that the join is returning is the prior record. Any thoughts on how to clear up this issue?

thanks!
newty25

Go to Top of Page

Page47
Master Smack Fu Yak Hacker

2878 Posts

Posted - 2002-06-28 : 09:20:51
Mabye you need to specify ASC or DESC in the order by. ASC is the default, on a default installation, with the default characterset/codepage, but your installation may be differnt. Without sample data, its difficult for me to test/debug. Your image links aren't working, either.

<O>
Go to Top of Page

Arnold Fribble
Yak-finder General

1961 Posts

Posted - 2002-06-28 : 09:34:17
quote:

newty25, the select into should honor the order by when making the RowNum column. I've done it many times. I could be wrong, but maybe you should check your rowset once more...



It's not this bug manifesting, is it?
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=14988

Go to Top of Page

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-06-28 : 09:37:50
Certainly looks to be, if newty is running SQL 7.0.

Jonathan Boott, MCDBA
Go to Top of Page

newty25
Starting Member

21 Posts

Posted - 2002-06-28 : 14:25:43
i am running v7. Thanks, Arnold Fribble. I was beginning to think that I was seeing things.

newty25

Go to Top of Page
   

- Advertisement -