November 1, 2010 at 11:31 am
I'm building a procedure which will create records of inventory items to be counted over a 2 year period. There are a number of factors which determine how many times an item must be counted within a single year, the maximum number of items that can be counted each day and the maximum number of units per item per day.
I've configured the procedure to use nested cursors. I've place the code below, but its very long and I wouldn't expect anyone to actually read through it all. Basically, here's what it does.
1) Starts a While loop for each year in the 2 year period (2010 & 2011) (loop 1) non-cursor (sort of)
2) Sets a variable with the number of countable days within the year
2) Loops through all available count days within the year variable (pulls from a 'Days' table which includes a 'blockoutdate' bit field to flag those days on which cycle counts cannot be performed. (loop 2) cursor
3) The inventory counts are segregated by zones. A table has been created that stores the key zone attributes, namely which items are in each zone and the thresholds (maximums) for daily item counts and daily units count. Loops through each zone. (loop 3) cursor
4) Loops through each unique CountFrequency found in the list of items within each zone. Count frequencies = 0 (never count), 1 (count one over the entire 2 year period), 2 (count twice a year, or 4 times over the two year period). (loop 4) cursor
5) Set a couple of variables to calculate the item spread over the period (numberofUniqueItems / numberofavailabledays) = number of skus per day.
6) Loops through each item with the zone. (loop 5) cursor
7) Exec sp to insert records into a Counts table.
Needless to day, this procedure takes a very long time to run. I've read several articles and blogs regarding cursors versus set-based processing, but I cannot visualize anyway to accomplish this without using cursors. I liken it to being a poker dealer, dealing out the cards to each player, but not every player gets a card everytime. I know there has to be a better way, but I need someone smarter than I to point me in that direction. Thanks in advance.
SET NOCOUNT ON
Decalre @ScheduleID bigint
--Set @ScheduleID = 2
declare @BDate datetime, @EDate datetime, @Date datetime, @Item nvarchar(50), @QOH decimal(10, 2), @ZoneCode nvarchar(50),
@QTY decimal(10, 2), @Year int, @NumOfYears int, @YearCounter int, @Whse nchar(2) ,@TagNo nvarchar(50), @SIID bigint,
@pass int, @MaxCountsPerSchedule int, @TagCounter int, @MaxItemsPerCount int, @ItemCount int,
@ZoneID bigint, @SheetNo int, @UnitThreshold bigint, @NumberOfDays int, @NumberOfSKUs int, @RowCount int,
@CountFreq nvarchar(5), @NumOfMonths int, @MonthsToAdd int, @Freq int
Set @BDate = (Select BDate from cc.Schedules where ID = @ScheduleID)
Set @EDate = (Select EDate from cc.Schedules where ID = @ScheduleID)
Set @NumOfYears = Year(@EDate) - Year(@BDate) + 1
Set @Year = year(@BDate)
Set @YearCounter = 0
Set @ItemCount = 0
Set @NumOfMonths = dbo.fnNumberOfMonths(@BDate, @EDate)
Set @pass = 0
Set @MaxCountsPerSchedule = (Select Max(Frequency)
from cc.FrequencyCodes F Join cc.ScheduleItems S
on F.FrequencyCode = S.CountFrequency
Where S.SID = @ScheduleID)
While @YearCounter < @NumOfYears
Begin
NextYear:
-- Go through every item in the list that's not a 'Z' item.
NextPass:
-- Select every date that hasn't been blocked out.
Set @NumberofDays = (Select count(fDate)
From Reporting.dbo.Dates
Where fDate between @BDate and @EDate
And year(fDate) = @Year
And BlockOutDate = 0)
declare csrDates1 cursor for Select fDate
From Reporting.dbo.Dates
Where fDate between @BDate and @EDate
And year(fDate) = @Year
And BlockOutDate = 0
order by fdate
Open csrDates1
Fetch next from csrDates1 into @Date
While @@Fetch_Status = 0
Begin
-- Select a group of items which a sum total of QOH =< 2000 from within the same zone.
If @pass = 2
Begin
Set @Date = cc.NextOpenDate(@Date)
End
Set @QTY = 0
Set @TagCounter = 1
Set @SheetNo = 1
-- Zone Info
declare csrZoneInfo cursor for Select WhseID, Zone, CountThreshold, ID, UnitThreshold
from cc.Zones
Where ID in (Select ZID from cc.ScheduleItems Where SID = @ScheduleID
Group by ZID)
Group by WhseID, Zone, CountThreshold, ID, UnitThreshold
Order by CountThreshold
open csrZoneInfo
Fetch Next from csrZoneInfo into @Whse, @ZoneCode, @MaxItemsPerCount, @ZoneID, @UnitThreshold
While @@Fetch_Status = 0
Begin
-- Count Freqs
Declare csrCountFreqs cursor for Select CountFrequency
from cc.ScheduleItems
Where [SID] = @ScheduleID
and [ZID] = @ZoneID
and CountFrequency <> 'Z'
Group by CountFrequency
Order by CountFrequency
Open csrCountFreqs
Fetch Next from csrCountFreqs into @CountFreq
While @@Fetch_Status = 0
Begin
Set @QTY = 0
Set @NumberOfSKUs = (Select count(*)
FROM cc.ScheduleItems SI
Where [SID] = @ScheduleID
and [ZID] = @ZoneID
and SI.CountFrequency = @CountFreq
and CompletedCounts < (Select Frequency from cc.FrequencyCodes Where FrequencyCode = @CountFreq and Whse = @Whse)
and AssignedCount = @pass
and Scheduled = 0)
-- 213
If @NumberOfSKUs <= @NumberOfDays/2 -- 177
Begin
Set @Rowcount = 1
End
If @NumberOfSKUs > @NumberOfDays/2
Begin
Set @Rowcount = ceiling((@NumberOfSKUs / (@NumberOfDays/2)))
End
--Select @NumberOfSKUs as [Number of SKUs], @NumberOfDays as [Number of Days], ceiling((@NumberOfSKUs / (@NumberOfDays/2))) as [Calc Value], @Rowcount as [Row Count]
Set Rowcount @Rowcount
-- Items
Declare csrItems cursor for
Select ItemNo, QOH, SI.ID
FROM cc.ScheduleItems SI
Where [SID] = @ScheduleID
and [ZID] = @ZoneID
and SI.CountFrequency = @CountFreq
and CompletedCounts < (Select Frequency from cc.FrequencyCodes Where FrequencyCode = @CountFreq and Whse = @Whse)
and AssignedCount = @pass
and Scheduled = 0
order by ItemNo
Open csrItems
Fetch Next from csrItems into @Item, @QOH, @SIID
While @@Fetch_Status = 0
Begin
Set @Freq = (Select Frequency from cc.FrequencyCodes Where FrequencyCode = @CountFreq and Whse = @Whse)
Set @MonthsToAdd = (@NumOfMonths / @Freq)
Set @Date = (Select
Case
When @pass = 0 Then @Date
When @pass > 0 and @pass < @Freq Then DateAdd(mm, @MonthsToAdd, @Date)
End)
Set @TagNo = rtrim(@ZoneCode) + '-' + rtrim(cast(@TagCounter as varchar(3)))
EXEC cc.InsertNewCount @SIID, @Item, @TagNo, @Date, @SheetNo, @ZoneID, @QOH -- Remove @QOH after testing.
If @pass + 1 < @MaxCountsPerSchedule
Begin
Update cc.ScheduleItems
Set AssignedCount = @pass + 1
Where ID = @SIID
End
If @pass + 1 = @MaxCountsPerSchedule
Begin
Update cc.ScheduleItems
Set Scheduled = 1, AssignedCount = @pass + 1
Where ID = @SIID
End
Set @QTY = @QTY + @QOH
Set @TagCounter = @TagCounter + 1
Set @ItemCount = @ItemCount + 1
If @QTY >= @UnitThreshold GoTo NextCountFreq
If @ItemCount = @MaxItemsPerCount GoTo NextCountFreq
Fetch Next from csrItems into @Item, @QOH, @SIID
-- Exit Items
End
NextCountFreq:
Set RowCount 0
Close csrItems
Deallocate csrItems
If @ItemCount = @MaxItemsPerCount GoTo NextZone
Fetch Next from csrCountFreqs into @CountFreq
-- Exit Count Freqs
End
NextZone:
Close csrCountFreqs
Deallocate csrCountFreqs
Set @ItemCount = 0
--Set @SheetNo = @SheetNo + 1
Set @TagCounter = 1
Set @ItemCount = 0
Set @SheetNo = @SheetNo + 1
Fetch Next from csrZoneInfo into @Whse, @ZoneCode, @MaxItemsPerCount, @ZoneID, @UnitThreshold
--ExitZones:
End
close csrZoneInfo
deallocate csrZoneInfo
Fetch next from csrDates1 into @Date
End
Close csrDates1
Deallocate csrDates1
--If @pass = 0 GoTo NextPass
Pass3:
If @pass = 2
Begin
End
If @pass + 1 < @MaxCountsPerSchedule GOTO NextPass
Set @Year = @Year + 1
Set @YearCounter = @YearCounter + 1
If @YearCounter < @NumOfYears GoTo NextYear
If @YearCounter = @NumOfYears GoTo ExitProc
End
ExitProc:
November 1, 2010 at 11:51 am
I was just thinking, I could insert all of the items into the table first since I already know how many times each should appear in the list.
Then either I come back afterwards and update the date or try to come up with a select statement that will derive the correct date while I'm inserting the items the first time.
Just thinking out loud here. . . .
November 1, 2010 at 11:56 am
I'm 98% sure it's possible to get you out of the cursor based methodology here. Can you post the DDLs for the involved tables and a bit of sample data (see first link in my signature) to give us a legup on helping you determine this?
Please make sure to include indexes with the DDL, it will help us with recommendations as well.
Never stop learning, even if it hurts. Ego bruises are practically mandatory as you learn unless you've never risked enough to make a mistake.
For better assistance in answering your questions[/url] | Forum Netiquette
For index/tuning help, follow these directions.[/url] |Tally Tables[/url]
Twitter: @AnyWayDBA
November 1, 2010 at 12:15 pm
In the sample data I've left out some of the extraneous data.
Zones:
CREATE TABLE [cc].[Zones](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Zone] [nvarchar](50) NULL,
[zDescription] [nvarchar](255) NULL,
[Inactive] [bit] NULL,
[TS] [timestamp] NULL,
[DateCreated] [datetime] NULL CONSTRAINT [DF_Zones_DateCreated] DEFAULT (getdate()),
[Definition] [nvarchar](max) NULL,
[LastUser] [nvarchar](50) NULL,
[LastAction] [nvarchar](50) NULL,
[WhseID] [nvarchar](2) NULL,
[Color] [nvarchar](100) NULL,
[CountThreshold] [int] NULL,
[UnitThreshold] [bigint] NULL,
[Printer] [nvarchar](256) NULL,
CONSTRAINT [PK_Zones] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Sample Zone Data:
ID Zone zDescription Whse CountThreshold UnitThreshold
1BWButtweld Fittings Class 2, buttweld fittings only0120 2000
2FLFlanges Class 3, Flanges 0110 2000
3PFPressure FittingsClass 2, Pressure Fittings 0110 2000
4PYPipe Yard Class 5 & 6, Pipe & Tubing 015 10000
5VLVValves Class 1 & 8, Valves 015 1500
cc:Schedules:
CREATE TABLE [cc].[Schedules](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](255) NULL,
[BDate] [datetime] NULL,
[EDate] [datetime] NULL,
[StatusID] [bigint] NULL,
[TS] [timestamp] NULL,
[DateCreated] [datetime] NULL,
[StatusChangeDate] [datetime] NULL,
[LastUser] [nvarchar](50) NULL,
[LastAction] [nvarchar](50) NULL,
[Compiled] [bit] NULL CONSTRAINT [DF_Schedules_Compiled] DEFAULT ((0)),
CONSTRAINT [PK_Schedules] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Sample Data:
ID TITLE BDate EndingDate
2Inventory Count Period 2010 thru 20112010-01-01 13:26:42.0002011-12-31 13:26:42.000
cc.ScheduleItems:
CREATE TABLE [cc].[ScheduleItems](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[SID] [bigint] NOT NULL,
[ZID] [bigint] NULL,
[ItemNo] [nvarchar](50) NULL,
[QOH] [decimal](10, 2) NULL,
[AvgCost] [decimal](10, 2) NULL,
[TS] [timestamp] NULL,
[CountFrequency] [nvarchar](5) NULL,
[CompletedCounts] [int] NULL CONSTRAINT [DF_ScheduleItems_CompletedCounts] DEFAULT ((0)),
[LastCountDate] [datetime] NULL,
[Scheduled] [bit] NULL CONSTRAINT [DF_ScheduleItems_Scheduled] DEFAULT ((0)),
[AssignedCount] [int] NULL,
CONSTRAINT [PK_ScheduleItems] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Sample Data:
ID SchdID ZID ItemNo QOH CntFreq ScheduledCountDate Schd AssignedCounts
53177210201002050AA040000000000 0.00B1900-01-01 00:00:00.00002
5317821020100240045012000000C00 0.00B1900-01-01 00:00:00.00002
53179210201006100LA025000000000 0.00B1900-01-01 00:00:00.00002
531802145005100020IY 94.00B1900-01-01 00:00:00.00002
531812145005100020IY00000000 0.00B1900-01-01 00:00:00.00002
531822145005100020IY000000SF139 0.00B1900-01-01 00:00:00.00002
531832145005100030IY 0.00B1900-01-01 00:00:00.00002
531842145005100030IY00000000 0.00B1900-01-01 00:00:00.00002
531852145005100060DY 52.00B1900-01-01 00:00:00.00002
531862145005100060DY0000000F132 29.00Z1900-01-01 00:00:00.00000
cc.FrequencyCodes:
CREATE TABLE [cc].[FrequencyCodes](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Whse] [nchar](2) NULL,
[FrequencyCode] [nvarchar](2) NULL,
[Frequency] [int] NULL,
[Inactive] [bit] NULL,
[TS] [timestamp] NULL,
CONSTRAINT [PK_FrequencyCodes] PRIMARY KEY CLUSTERED
Sample Data:
ID Whse Code Freq
101A4
201B1
301Z0
402A1
502B1
602Z0
705A1
805B1
cc.Counts:
CREATE TABLE [cc].[Counts](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[SIID] [bigint] NOT NULL,
[ZID] [bigint] NULL,
[SupervisorID] [bigint] NULL,
[CountedBy] [bigint] NULL,
[CheckedBy] [bigint] NULL,
[ScheduledCountDate] [datetime] NULL,
[StatusID] [bigint] NULL,
[DateCreated] [datetime] NULL,
[TagNo] [nvarchar](50) NULL,
[SheetNo] [int] NULL,
[ItemNo] [nvarchar](50) NOT NULL,
[CountQty] [decimal](10, 2) NULL CONSTRAINT [DF_CountDetails_CountQty] DEFAULT ((0)),
[AllocatedQty] [decimal](10, 2) NULL CONSTRAINT [DF_CountDetails_AllocatedQty] DEFAULT ((0)),
[StagedQty] [decimal](10, 2) NULL CONSTRAINT [DF_CountDetails_StagedQty] DEFAULT ((0)),
[DockQty] [decimal](10, 2) NULL CONSTRAINT [DF_CountDetails_DockQty] DEFAULT ((0)),
[SysQOH] [decimal](10, 2) NULL CONSTRAINT [DF_CountDetails_SysQOH] DEFAULT ((0)),
[VarianceQty] [decimal](10, 2) NULL,
[UnitCost] [decimal](10, 2) NULL,
[Variance$] [decimal](10, 2) NULL,
[TolQty] [bigint] NULL,
[Tol$] [bigint] NULL,
[TolQtyPer] [bigint] NULL,
[Tol$Per] [bigint] NULL,
[Recount] [bit] NULL CONSTRAINT [DF_CountDetails_Recount] DEFAULT ((0)),
[Recounted] [bit] NULL CONSTRAINT [DF_CountDetails_Recounted] DEFAULT ((0)),
[OriginalTagNo] [nvarchar](50) NULL,
[Notes] [nvarchar](max) NULL,
[LastUser] [nvarchar](50) NULL,
[LastAction] [nvarchar](50) NULL,
[TeamID] [bigint] NULL,
[TS] [timestamp] NULL,
[CompletedDate] [datetime] NULL CONSTRAINT [DF_Counts_CompletedDate] DEFAULT (((1900)-(1))-(1)),
[Completed] [bit] NULL CONSTRAINT [DF_Counts_Completed] DEFAULT ((0)),
CONSTRAINT [PK_Counts_1] PRIMARY KEY CLUSTERED
No sample data.
November 1, 2010 at 12:21 pm
T3mplarKn1ght (11/1/2010)
In the sample data I've left out some of the extraneous data.
Please go back to the link that Craig pointed you to, and read that article (it's the same as the first link in my signature). Then please post your sample data in the form of INSERT statements - to be useful to us where it can be tested, this needs to be done. Also, please provide what your expected results should be, based upon the sample data that you have provided.
Edit:
Can you also post the code for these procedures called by your procedure?
dbo.fnNumberOfMonths
cc.NextOpenDate
cc.InsertNewCount
(It helps if you put your code within the [ code = "sql"] / [ / code] tags (without spaces). This is available in the "IFCode Shortcuts" just to the left of the edit window when posting. Quote my message to see how it was done above.)
I agree with Craig that this looks like it can be converted into a set-based solution instead of using that c.u.r.s.o.r.!
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
November 1, 2010 at 12:35 pm
Templar,
Trying to turn that into a usable test set and running into some issues. Biggest one is you trimmed (not sure how) some of the PRIMARY KEY builds.
For example:
CONSTRAINT [PK_Counts_1] PRIMARY KEY CLUSTERED
It has no column definition. Can you double check some of this wasn't trimmed? FrequencyCode and Zones have similar issues.
For the data itself... I've built this in case anyone else is interested in tackling it, once we get cleaned up the table DDL:
SET IDENTITY_INSERT Zones ON
INSERT INTO Zones (ID, Zone, zDescription, Whse, CountThreshold, UnitThreshold)
SELECT 1, 'BW', 'Buttweld Fittings Class 2, buttweld fittings only', 01, 20, 2000 UNION ALL
SELECT 2, 'FL', 'Flanges Class 3, Flanges', 01, 10, 2000 UNION ALL
SELECT 3, 'PF', 'Pressure Fittings Class 2, Pressure Fittings', 01, 10, 2000 UNION ALL
SELECT 4, 'PY', 'Pipe Yard Class 5 & 6, Pipe & Tubing', 01, 5, 10000 UNION ALL
SELECT 5, 'VLV', 'Valves Class 1 & 8, Valves', 01, 5, 1500
SET IDENTITY_INSERT Zones OFF
SET IDENTITY_INSERT Schedules ON
INSERT INTO Schedules( ID, TITLE, BDate , EndingDate)
SELECT 2, 'Inventory Count Period 2010 thru 2011', '2010-01-01 13:26:42.000', '2011-12-31 13:26:42.000'
SET IDENTITY_INSERT Schedules OFF
SET IDENTITY_INSERT ScheduleItems ON
INSERT INTO ScheduleItems( ID, SchdID, ZID, ItemNo, QOH, CntFreq, ScheduledCountDate, Schd, AssignedCounts)
SELECT 53177, 2, 1, '0201002050AA040000000000', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53178, 2, 1, '020100240045012000000C00', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53179, 2, 1, '0201006100LA025000000000', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53180, 2, 1, '45005100020IY', 94.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53181, 2, 1, '45005100020IY00000000', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53182, 2, 1, '45005100020IY000000SF139', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53183, 2, 1, '45005100030IY', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53184, 2, 1, '45005100030IY00000000', 0.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53185, 2, 1, '45005100060DY', 52.00, 'B', '1900-01-01 00:00:00.000', 0, 2 UNION ALL
SELECT 53186, 2, 1, '45005100060DY0000000F132', 29.00, 'Z', '1900-01-01 00:00:00.000', 0, 0
SET IDENTITY_INSERT ScheduleItems OFF
SET IDENTITY_INSERT FrequencyCodes ON
INSERT INTO FrequencyCodes ( ID, Whse, Code, Freq)
SELECT 1, '01', 'A', 4 UNION ALL
SELECT 2, '01', 'B', 1 UNION ALL
SELECT 3, '01', 'Z', 0 UNION ALL
SELECT 4, '02', 'A', 1 UNION ALL
SELECT 5, '02', 'B', 1 UNION ALL
SELECT 6, '02', 'Z', 0 UNION ALL
SELECT 7, '05', 'A', 1 UNION ALL
SELECT 8, '05', 'B', 1
SET IDENTITY_INSERT FrequencyCodes OFF
Never stop learning, even if it hurts. Ego bruises are practically mandatory as you learn unless you've never risked enough to make a mistake.
For better assistance in answering your questions[/url] | Forum Netiquette
For index/tuning help, follow these directions.[/url] |Tally Tables[/url]
Twitter: @AnyWayDBA
November 1, 2010 at 12:39 pm
I appreciate that you guys are willing to go so far as to replicate the tables, data, etc. but that's way more than I could ask.
I was really looking for some general, 'this is what I've done in the past' type insight.
I'm sure you guys have better things to do than just work on my procedure.
Now that I've taken the time to jot everything down and think it out, I think the best approach will be to start from the inside of the nested cursors and work my way out, trying to eliminate each cursor level via an update statement. (i.e. insert all of the items, then determine the best count date, then derive the tag sheet numbers.
Thanks again.
November 1, 2010 at 12:44 pm
That's kinda what we'd end up doing. Part of the reason I'm trying to get to the core of the data is because I'd actually completely rebuild from scratch just on the business logic. Without the schema and sample data, there's no way to rationally test it to make sure it would work within your design.
For general advice, however, I'd scrap what you're staring at in the procedure and start over from the logic itself. Once you're done, revisit the old procedure and doublecheck where clauses and any other minor tweaks that got involved since the original business definition are included. Then do side by side testing to confirm no logic failures.
Never stop learning, even if it hurts. Ego bruises are practically mandatory as you learn unless you've never risked enough to make a mistake.
For better assistance in answering your questions[/url] | Forum Netiquette
For index/tuning help, follow these directions.[/url] |Tally Tables[/url]
Twitter: @AnyWayDBA
November 1, 2010 at 12:49 pm
Thanks, I'll do that.
November 1, 2010 at 1:32 pm
T3mplarKn1ght (11/1/2010)
I appreciate that you guys are willing to go so far as to replicate the tables, data, etc. but that's way more than I could ask.
Turning down free help, are we??? :w00t::-P:-D
Seriously, doing this type of stuff is actually beneficial to us... "Use it or lose it", etc. Helps keep us sharp. Let's us do things we might not do otherwise, and learn in the process. (In another thread, Craig just showed me a better way to do something... )
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
Viewing 10 posts - 1 through 10 (of 10 total)
You must be logged in to reply to this topic. Login to reply