August 22, 2007 at 9:23 am
I'm looking for some advice on a query that I have written.
Example table that I will work with:
-------------
|CallID|UCID|
=============
| 1230 |aaaa|
| 1230 |bbbb|
| 2520 |bbbb|
| 5555 |bbbb|
| 6665 |cccc|
-------------
Now the first 4 rows are linked and the way you can tell this is by jumping from one column to the other eg:
CallID 1230 has a UCID values of "aaa" and "bbb"
Now look at the CallID's based on the UCID in the previous line you CallIDs of 1230 and 2520
repeat jumping across from one field to another until you get no more new UCID's or CallID's.
At this point I want to make it clear that the table was not written by me but by an external company.
What I'm trying to do is to add a new column that is a grouping column, so that when you query this data you don't have to move from one column to another to find out if the next row is linked or not.
So here is my code to resolve it:
DECLARE @MaxLoop INT
DECLARE @Looper INT
DECLARE @CountUCIDs TINYINT
DECLARE @CountCallIDs TINYINT
DECLARE @InnerLoop TINYINT
DECLARE @StartCount TINYINT
DECLARE @EndCount TINYINT
DECLARE @UCIDStatus TINYINT
DECLARE @CallIDStatus TINYINT
DECLARE @NewGroupID INT
SET @MaxLoop = 0
SET @Looper = 0
SET @InnerLoop = 1
SET @CountUCIDs = 0
SET NOCOUNT ON
DECLARE @NewUCIDVals TABLE (UCID VARCHAR(20) COLLATE Latin1_General_CI_AS NOT NULL)
DECLARE @CallIDVals TABLE (CallID INT NOT NULL)
SELECT @MaxLoop = COUNT(*) FROM dbo.TempLoadRawCmsCallHistory
WHILE @looper < @MaxLoop
BEGIN
--Get a UCID from the loading table
INSERT INTO @NewUCIDVals
SELECT TOP 1 UCID FROM dbo.TempLoadRawCmsCallHistory
--Now find all callID's linked to the UCID
INSERT INTO @CallIDVals
SELECT CallID FROM dbo.TempLoadRawCmsCallHistory WHERE UCID IN(SELECT UCID FROM @NewUCIDVals)
--Now check to see if there are more than one UCID assoicated with CallID
SET @CountUCIDs = 2
IF @CountUCIDs > 1 --There are more records, record them
BEGIN
--poss this is a multi event call need to find any other ucids and other callids
While @InnerLoop < 100
BEGIN
--Remember how many records are the ucid hash table
SET @StartCount = (SELECT COUNT(*) FROM @NewUCIDVals)
--Store all of the UCID's found
INSERT INTO @NewUCIDVals
SELECT UCID FROM dbo.TempLoadRawCmsCallHistory WHERE CallID IN (SELECT CallID FROM @CallIDVals) AND UCID NOT IN (SELECT UCID FROM @NewUCIDVals)
--Now check how many records there are now
SET @EndCount = (SELECT COUNT(*) FROM @NewUCIDVals)
IF @StartCount = @EndCount
BEGIN
SET @UCIDStatus = 1
--Reset the counter as they will be used to check the callID's
SET @StartCount = 0
SET @EndCount = 0
END
ELSE
BEGIN
SET @UCIDStatus = 0
--Reset the counter as they will be used to check the callID's
SET @StartCount = 0
SET @EndCount = 0
END
--Remember how many records are the CallID hash table
SET @StartCount = (SELECT COUNT(*) FROM @CallIDVals)
--Now Check to see if you have any new Callids
INSERT INTO @CallIDVals
SELECT CallID FROM dbo.TempLoadRawCmsCallHistory WHERE UCID IN(SELECT UCID FROM @NewUCIDVals) AND CallID NOT IN (SELECT CallID FROM @CallIDVals)
--Now check how many records there are now
SET @EndCount = (SELECT COUNT(*) FROM @CallIDVals)
IF @StartCount = @EndCount
BEGIN
SET @CallIDStatus = 1
--Reset the counter as they will be used to check the UCID's
SET @StartCount = 0
SET @EndCount = 0
END
ELSE
BEGIN
SET @CallIDStatus = 0
--Reset the counter as they will be used to check the UCID's
SET @StartCount = 0
SET @EndCount = 0
END
IF @CallIDStatus + @UCIDStatus = 2
BEGIN
SET @InnerLoop = 101
SET @CallIDStatus = 0
SET @UCIDStatus = 0
END
ELSE
BEGIN
SET @CallIDStatus = 0
SET @UCIDStatus = 0
SET @InnerLoop = @InnerLoop + 1
END
END
END
--Now you know all of the sections to the call do something
SELECT @NewGroupID = CASE WHEN MAX(GROUPID) IS NULL THEN 1 ELSE MAX(GROUPID) + 1 END FROM TempLoadGroupedCmsCallHistory
INSERT INTO TempLoadGroupedCmsCallHistory
SELECT *, @NewGroupID,0 FROM TempLoadRawCmsCallHistory WHERE UCID IN(SELECT DISTINCT * FROM @NewUCIDVals) AND CallID IN(SELECT DISTINCT * FROM @CallIDVals)
DELETE FROM TempLoadRawCmsCallHistory WHERE UCID IN(SELECT DISTINCT * FROM @NewUCIDVals) AND CallID IN(SELECT DISTINCT * FROM @CallIDVals)
--TRUNCATE TABLE @NewUCIDVals
--TRUNCATE TABLE @CallIDVals
DELETE FROM @CallIDVals
DELETE FROM @NewUCIDVals
SET @InnerLoop = 0
--move to the next call
SET @looper = (@MaxLoop - (SELECT COUNT(*) FROM TempLoadRawCmsCallHistory))
END
--DROP TABLE @NewUCIDVals
--DROP TABLE @CallIDVals
The problem I have is that running a trace whilst the code is executing is showing that the following line is holding the process up badly:
INSERT INTO @NewUCIDVals SELECT UCID FROM dbo.TempLoadRawCmsCallHistory WHERE CallID IN (SELECT CallID FROM @CallIDVals) AND UCID NOT IN (SELECT UCID FROM @NewUCIDVals) --Now check how many records there are now
Duration = avg 119
CPU = avg 119
Reads = avg 252
I have checked the Stats all all have checked the indexes. So any anyone suggest a way of improving the speed of this process
August 22, 2007 at 10:27 am
It would help if you could show an example of how the new column's data should look. Can you take your sample data and show how the data for the new column should look?
August 23, 2007 at 12:26 am
Hi John here you go:
---------------------------
|CallID|UCID|GroupID|
===============
| 1230 |aaaa| 12 |
| 1230 |bbbb| 12 |
| 2520 |bbbb| 12 |
| 5555 |bbbb| 12 |
| 6665 |cccc| 13 |
-------------
The group ID is there to group rows of data so when end users are querying data they do not need to write complex code to group all segments they can just utilise the groupid.
Hope this helps
Mark
August 23, 2007 at 8:24 am
When I run your code with your sample data, I do not get the results that you show here. Here's what I get, can you clarify?
CallID UCID GroupID
----------- ---------- -----------
1230 aaaa 1
1230 bbbb 1
2520 bbbb 1
5555 bbbb 1
6665 cccc 2
August 23, 2007 at 9:06 am
is there an identity key on this table, or is what you show the entire table definition? also, does the initial order of the rows need to remain intact?
Best,
Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru on googles mail service
August 23, 2007 at 9:36 am
I'm not sure if this is much more efficient and there is probably a better method to this madness, but here's an example of code that will produce the same results as yours, but with trimmed down logic and looping. The statement that you are saying that this hangs up on may be due to the lack of indexing on your table variables in combination with JOINing it back to your temp tables. How many rows are you working with here?
SET NOCOUNT ON
DECLARE @TempLoadGroupedCmsCallHistory TABLE (CallID int, UCID varchar(10), GroupID int, OtherCol int)
DECLARE @TempLoadRawCmsCallHistory TABLE (CallID int, UCID varchar(10))
INSERT INTO @TempLoadRawCmsCallHistory
SELECT 1230, 'aaaa' UNION ALL
SELECT 1230, 'bbbb' UNION ALL
SELECT 2520, 'bbbb' UNION ALL
SELECT 5555, 'bbbb' UNION ALL
SELECT 6665, 'cccc'
DECLARE @NewUCIDVals TABLE (UCID VARCHAR(20))-- COLLATE Latin1_General_CI_AS NOT NULL)
DECLARE @CallIDVals TABLE (CallID INT NOT NULL)
DECLARE
@NewGroupID INT,
@intRowCount int,
@intOuterCount int
SET @intOuterCount = -1
WHILE @intOuterCount <> 0
BEGIN
DELETE FROM @CallIDVals
DELETE FROM @NewUCIDVals
--get first row
INSERT INTO @NewUCIDVals
SELECT TOP 1 t1.UCID
FROM @TempLoadRawCmsCallHistory t1
LEFT JOIN @TempLoadGroupedCmsCallHistory t2
ON t1.UCID = t2.UCID
WHERE t2.UCID IS NULL
SELECT @intRowCount = @@ROWCOUNT, @intOuterCount = @@ROWCOUNT
WHILE @intRowCount > 0
BEGIN
--Now find all callID's linked to the UCID
INSERT INTO @CallIDVals
SELECT DISTINCT t1.CallID
FROM @TempLoadRawCmsCallHistory t1
INNER JOIN @NewUCIDVals t2
ON t1.UCID = t2.UCID
LEFT JOIN @CallIDVals t3
ON t1.CallID = t3.CallID
WHERE t3.CallID IS NULL
INSERT INTO @NewUCIDVals
SELECT t1.UCID
FROM @TempLoadRawCmsCallHistory t1
INNER JOIN @CallIDVals t2
ON t1.CallID = t2.CallID
LEFT JOIN @NewUCIDVals t3
ON t1.UCID = t3.UCID
WHERE t3.UCID IS NULL
SET @intRowCount = @@ROWCOUNT
END
SELECT @NewGroupID = CASE WHEN MAX(GROUPID) IS NULL THEN 1 ELSE MAX(GROUPID) + 1 END FROM @TempLoadGroupedCmsCallHistory
INSERT INTO @TempLoadGroupedCmsCallHistory
SELECT t1.*, @NewGroupID,0
FROM @TempLoadRawCmsCallHistory t1
INNER JOIN @NewUCIDVals t2
ON t1.UCID = t2.UCID
INNER JOIN @CallIDVals t3
ON t1.CallID = t3.CallID
END
SELECT CallID, UCID, GroupID FROM @TempLoadGroupedCmsCallHistory
August 23, 2007 at 9:39 am
Sorry John
You are correct you will get in the groupid column 1 then two. The value 12, 13 were just random numbers for example purposes only.
August 23, 2007 at 9:40 am
TheSQLGuru
There are no Identity Keys on the tables.
Cheers
Mark
August 23, 2007 at 9:40 am
John
Thank you I will try your code and get back to you.
Cheers
Mark
August 23, 2007 at 9:42 am
Hi John
the table TempLoadRawCmsCallHistory has anything from 191,000 through to 400,000 depending on the number of calls the business receives.
August 23, 2007 at 9:51 am
The main table that contains 191,000 to 400,000 is more than just two columns, I trimmed it down for ease of reading but below is the full table structure with indexes:
This is the raw table before grouping is applied-----
CREATE TABLE [TempLoadRawCmsCallHistory] (
[SOURCEID] [int] NOT NULL ,
[ROWDATE] [int] NOT NULL ,
[CALLID] [int] NOT NULL ,
[SEGMENT] [int] NOT NULL ,
[SEGSTART] [datetime] NOT NULL ,
[SEGSTOP] [datetime] NULL ,
[UCID] [varchar] (20) COLLATE Latin1_General_CI_AS NOT NULL ,
[ACWTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ACWTI__18EBB532] DEFAULT (0),
[AGT_RELEASED] [int] NOT NULL CONSTRAINT [DF__TempLoadR__AGT_R__19DFD96B] DEFAULT (0),
[ANSHOLDTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ANSHO__1AD3FDA4] DEFAULT (0),
[ANSLOCID] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ANSLO__1BC821DD] DEFAULT (0),
[ANSLOGIN] [varchar] (10) COLLATE Latin1_General_CI_AS NULL ,
[ANSREASON] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ANSRE__1CBC4616] DEFAULT (0),
[ASSIST] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ASSIS__1DB06A4F] DEFAULT (0),
[AUDIO] [int] NOT NULL CONSTRAINT [DF__TempLoadR__AUDIO__1EA48E88] DEFAULT (0),
[CALLING_II] [char] (2) COLLATE Latin1_General_CI_AS NULL ,
[CALLING_PTY] [varchar] (12) COLLATE Latin1_General_CI_AS NULL ,
[CONFERENCE] [int] NOT NULL CONSTRAINT [DF__TempLoadR__CONFE__1F98B2C1] DEFAULT (0),
[CONSULTTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__CONSU__208CD6FA] DEFAULT (0),
[CWC1] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[CWC2] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[CWC3] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[CWC4] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[CWC5] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[DA_QUEUED] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DA_QU__2180FB33] DEFAULT (0),
[DIALED_NUM] [varchar] (24) COLLATE Latin1_General_CI_AS NULL ,
[DISPIVECTOR] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPI__22751F6C] DEFAULT (0),
[DISPOSITION] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPO__236943A5] DEFAULT (0),
[DISPPRIORITY] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPP__245D67DE] DEFAULT (0),
[DISPSKLEVEL] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPS__25518C17] DEFAULT (0),
[DISPSPLIT] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPS__2645B050] DEFAULT (0),
[DISPTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DISPT__2739D489] DEFAULT (0),
[DISPVDN] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[DURATION] [int] NOT NULL CONSTRAINT [DF__TempLoadR__DURAT__282DF8C2] DEFAULT (0),
[EQLOCID] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EQLOC__29221CFB] DEFAULT (0),
[EQLOC] [varchar] (9) COLLATE Latin1_General_CI_AS NULL ,
[EVENT1] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2A164134] DEFAULT (0),
[EVENT2] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2B0A656D] DEFAULT (0),
[EVENT3] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2BFE89A6] DEFAULT (0),
[EVENT4] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2CF2ADDF] DEFAULT (0),
[EVENT5] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2DE6D218] DEFAULT (0),
[EVENT6] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2EDAF651] DEFAULT (0),
[EVENT7] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__2FCF1A8A] DEFAULT (0),
[EVENT8] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__30C33EC3] DEFAULT (0),
[EVENT9] [int] NOT NULL CONSTRAINT [DF__TempLoadR__EVENT__31B762FC] DEFAULT (0),
[FIRSTIVECTOR] [int] NOT NULL CONSTRAINT [DF__TempLoadR__FIRST__32AB8735] DEFAULT (0),
[FIRSTVDN] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[HELD] [int] NOT NULL CONSTRAINT [DF__TempLoadRa__HELD__339FAB6E] DEFAULT (0),
[HOLDABN] [int] NOT NULL CONSTRAINT [DF__TempLoadR__HOLDA__3493CFA7] DEFAULT (0),
[LASTCWC] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[LASTDIGITS] [varchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[LASTOBSERVER] [varchar] (10) COLLATE Latin1_General_CI_AS NULL ,
[MALICIOUS] [int] NOT NULL CONSTRAINT [DF__TempLoadR__MALIC__3587F3E0] DEFAULT (0),
[NETINTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__NETIN__367C1819] DEFAULT (0),
[OBSERVINGCALL] [int] NOT NULL CONSTRAINT [DF__TempLoadR__OBSER__37703C52] DEFAULT (0),
[OBSLOCID] [int] NOT NULL CONSTRAINT [DF__TempLoadR__OBSLO__3864608B] DEFAULT (0),
[ORIGHOLDTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ORIGH__395884C4] DEFAULT (0),
[ORIGLOCID] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ORIGL__3A4CA8FD] DEFAULT (0),
[ORIGLOGIN] [varchar] (10) COLLATE Latin1_General_CI_AS NULL ,
[ORIGREASON] [int] NOT NULL CONSTRAINT [DF__TempLoadR__ORIGR__3B40CD36] DEFAULT (0),
[SPLIT1] [int] NOT NULL CONSTRAINT [DF__TempLoadR__SPLIT__3C34F16F] DEFAULT (0),
[SPLIT2] [int] NOT NULL CONSTRAINT [DF__TempLoadR__SPLIT__3D2915A8] DEFAULT (0),
[SPLIT3] [int] NOT NULL CONSTRAINT [DF__TempLoadR__SPLIT__3E1D39E1] DEFAULT (0),
[TALKTIME] [int] NOT NULL CONSTRAINT [DF__TempLoadR__TALKT__3F115E1A] DEFAULT (0),
[TKGRP] [int] NOT NULL CONSTRAINT [DF__TempLoadR__TKGRP__40058253] DEFAULT (0),
[TRANSFERRED] [int] NOT NULL CONSTRAINT [DF__TempLoadR__TRANS__40F9A68C] DEFAULT (0),
[QUEUETIME] [int] NULL ,
[RINGTIME] [int] NULL ,
[VDN2] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN3] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN4] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN5] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN6] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN7] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN8] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[VDN9] [varchar] (7) COLLATE Latin1_General_CI_AS NULL ,
[UUILEN] [int] NULL ,
[ASAIUUI] [varchar] (192) COLLATE Latin1_General_CI_AS NULL ,
PRIMARY KEY CLUSTERED
(
[SOURCEID],
[ROWDATE],
[CALLID],
[SEGMENT]
) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE INDEX [TempLoadRawCmsCallHistory_I] ON [dbo].[TempLoadRawCmsCallHistory]([ROWDATE]) ON [PRIMARY]
GO
CREATE INDEX [TempLoadRawCmsCallHistory_SGSTRT] ON [dbo].[TempLoadRawCmsCallHistory]([SEGSTART]) ON [PRIMARY]
GO
CREATE INDEX [TempLoadRawCmsCallHistory_CALLID] ON [dbo].[TempLoadRawCmsCallHistory]([SOURCEID], [CALLID]) ON [PRIMARY]
GO
CREATE INDEX [TempLoadRawCmsCallHistory_UCID] ON [dbo].[TempLoadRawCmsCallHistory]([UCID]) ON [PRIMARY]
GO
When the routine finishes it places data into a mirror table but with one difference there is an additional column named groupid.
Hope this helps
Cheers Mark
August 23, 2007 at 12:27 pm
Mark, you didn't answer my second question about whether the order of the rows matters. If I move these rows into another table for processing, can I order them by firstcol/secondcol?
Oh, wait, never mind. I just looked at your FULL table definition. You ARE clustering on 4 columns --> we have both a key and a known order. Let me work on it a bit. May be a while though. I have production server issues at one of my clients at the moment.
Best,
Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru on googles mail service
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply