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.
| Author |
Topic |
|
SamC
White Water Yakist
3467 Posts |
Posted - 2003-10-08 : 09:45:12
|
| CREATE TABLE Users (UserId INT NOT NULL, -- ID of this userCompleted DATETIME NULL, -- date this user "completed"CreateDate DATETIME NOT NULL, -- Date this user record was addedDept INT -- Unique department identifier)Department 5 has "Completed" all users on May 1 (column "completed" holds a date and is NOT NULL) and is the first department to "Complete all users". In June, a new user is added to Department 5 and completes the same day.I need to build a SELECT that runs in October showing Department 5 was the first to reach 100% completion and the date that the last user completed (May 1). The "new user" problem is tripping me. More generally, the SELECT should list the departments that have reached 100% and when (date of last user completion in that department) they first reached 100%, even if a new user has been added later to the department (which may mean the department is not currently at 100%).Sounds like a Tally table is going to be in this one.Sam |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2003-10-08 : 09:52:04
|
shot in the darkselect dept, max(createdate) as 'last user completion'from users uwhere not exists ( select 1 from users where u.dept = dept and complete is null)group by dept Jay White{0} |
 |
|
|
SamC
White Water Yakist
3467 Posts |
Posted - 2003-10-08 : 10:04:24
|
| Thanks Jay,That query would eliminate a dept who completed in May, but added a new user in June that is currently holding a NULL completed column.A query will need to be have a granularity. DIGRESS: A department could reach 100% at 10:30 AM, but a new user added at 11 AM making the department 99% (not complete). Some figure of granularity has to be devised that is reasonable - day / week / month and the query will need to calculate the figures for each department in each granular segment. A department's 100% figure will be the first date that 100% completion is met.Sam |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-10-08 : 10:37:39
|
| Hi Sam --can you give us some sample data? and also what results you would like for that data? I'm having trouble grasping this one ...- Jeff |
 |
|
|
SamC
White Water Yakist
3467 Posts |
Posted - 2003-10-08 : 11:07:21
|
quote: We don't need no stinkin' sample data!
Dept UserID Completed CreateDate 5 1 May-1-2003 Jan-1-20035 2 May-6-2003 Jan-1-20035 3 May-9-2003 Jan-1-20035 4 Jun-2-2003 Jan-1-20035 5 Aug-9-2003 Aug-1-20034 6 May-3-2003 Jan-1-20034 7 May-11-2003 Jan-1-20034 8 May-18-2003 Jan-1-20034 9 May-20-2003 Jan-1-20034 10 NULL July-1-2003Sample data for depts 5 and 4 are given. Most users were "Created' January 1, 2003.Department 5 reached 100% completion when UserID 4 completed on June 2, 2003. At that time, all four of Department 5 users had completed. We know this because the Create Dates for all 4 users were less than the last completed date. Later, a 5th UserID 5 was added to Dept 5 and he completed on Aug 1, but this doesn't change the earliest date that 100% was reached.Department 4 is similar, having reached 100% completion on May 20, 2003. UserID 10 was added to Dept 4 on July 1, 2003 and remains NULL (incomplete) but this doesn't change the date Dept 5 reached 100%.Sometimes the difficulty of a solution relates to the complexity of the question. I'm not sure I'm positioning this question as clearly as it could be stated.Sam |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-10-08 : 11:54:51
|
Here's my shot...(Need some more poster-friendly sample data)Assumes an enrollment period to take care of your requirement about excluding :"stragglers"I think you're asking for the min of the max'sUSE NorthwindGOCREATE TABLE Users ( UserId int NOT NULL-- ID of this user , Completed datetime NULL -- date this user "completed" , CreateDate datetime NOT NULL-- Date this user record was added , Dept int NOT NULL-- Unique department identifier)GOINSERT INTO Users (Dept, UserID, Completed, CreateDate) SELECT 5, 1, 'May 1 2003', 'Jan 1 2003' UNION ALLSELECT 5, 2, 'May 6 2003', 'Jan 1 2003' UNION ALLSELECT 5, 3, 'May 9 2003', 'Jan 1 2003' UNION ALLSELECT 5, 4, 'Jun 2 2003', 'Jan 1 2003' UNION ALLSELECT 5, 5, 'Aug 9 2003', 'Aug 1 2003' UNION ALLSELECT 4, 6, 'May 3 2003', 'Jan 1 2003' UNION ALLSELECT 4, 7, 'May 11 2003', 'Jan 1 2003' UNION ALLSELECT 4, 8, 'May 18 2003', 'Jan 1 2003' UNION ALLSELECT 4, 9, 'May 20 2003', 'Jan 1 2003' UNION ALLSELECT 4, 10, NULL , 'July 1 2003'GODECLARE @StartEnrollPeriod datetime, @EndEnrollPeriod datetimeSELECT @StartEnrollPeriod = 'Jan 1 2003', @EndEnrollPeriod = 'Jan 31 2003'SELECT * FROM Users WHERE Completed = ( SELECT MIN(Max_Completed) AS Min_Max_Completed FROM ( SELECT Dept, Max(Completed) As Max_Completed FROM Users WHERE CreateDate >= @StartEnrollPeriod AND CreateDate <= @EndEnrollPeriod GROUP BY Dept) AS XXX)DROP TABLE UsersGO Brett8-)SELECT @@POST FROM Brain ORDER BY NewId()That's correct! It's an AlphaNumeric! |
 |
|
|
SamC
White Water Yakist
3467 Posts |
Posted - 2003-10-08 : 12:28:26
|
| Hi Brett and Thanks,Taking an Enrollment period approach may be the most reasonable way to a clear SELECT that works.I should've (but didn't) post what I had hoped would be the output result. Here it is:DEPARTMENT CompletionDate5 June 2, 20034 May 20, 2003Departments that have never reached 100% are not included in the report.But before tweaking the SELECT you proposed to meet the resultset format, there is a problem with the psychology of the "Enrollment period" idea. If you are a department manager, and there's a reward based upon being first department to reach 100% completion. It might bother you if another department won 1st place, but had a significant transfer of incompleted users to their organization after the enrollment period (which were not counted).A solution that calculates the Department completion percentages on a periodic (weekly ?) basis is the only solution that will keep tempers from flaring.I have some ideas that I'll post later today, unless someone beats me to it.Sam |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-10-08 : 12:41:26
|
quote: Originally posted by SamC Hi Brett and Thanks,
Your welcome[qoute]Taking an Enrollment period approach may be the most reasonable way to a clear SELECT that works. Well it's part of your requirement...SQL's good..but...quote: I should've (but didn't) post what I had hoped would be the output result. Here it is:DEPARTMENT CompletionDate5 June 2, 20034 May 20, 2003
That helps...thought you wanted the first 1 though, not all then last completions...quote: Departments that have never reached 100% are not included in the report.
I guess that would be anyone with a Null Completion Date, no?quote: But before tweaking the SELECT you proposed to meet the resultset format, there is a problem with the psychology of the "Enrollment period" idea. If you are a department manager, and there's a reward based upon being first department to reach 100% completion. It might bother you if another department won 1st place, but had a significant transfer of incompleted users to their organization after the enrollment period (which were not counted).
OK...but you must have some rules you can followquote: A solution that calculates the Department completion percentages on a periodic (weekly ?) basis is the only solution that will keep tempers from flaring.[/quote]Why would a period make any difference?I'm thinking you'll need more meterics than just completed.Looks like Good kayaking weather...You should let them beat on each other...no need for a report then..Better yet...tell them the code was too complicated and you keep the reward... Brett8-)SELECT @@POST FROM Brain ORDER BY NewId()That's correct! It's an AlphaNumeric! |
 |
|
|
SamC
White Water Yakist
3467 Posts |
Posted - 2003-10-08 : 16:26:48
|
Hi Brett. I regret I couldn't explain the problem better, but here's a solution that uses a date Tally table.Here's the result of the following query.Dept,CompletedDate4,2003-05-20 00:00:00.0005,2003-06-02 00:00:00.000
DROP TABLE dbo.xUsersGOCREATE TABLE dbo.xUsers ( UserId int NOT NULL-- ID of this user , Completed datetime NULL -- date this user "completed" , CreateDate datetime NOT NULL-- Date this user record was added , Dept int NOT NULL-- Unique department identifier)GOINSERT INTO xUsers (Dept, UserID, Completed, CreateDate) SELECT 5, 1, 'May 1 2003', 'Jan 1 2003' UNION ALLSELECT 5, 2, 'May 6 2003', 'Jan 1 2003' UNION ALLSELECT 5, 3, 'May 9 2003', 'Jan 1 2003' UNION ALLSELECT 5, 4, 'Jun 2 2003', 'Jan 1 2003' UNION ALLSELECT 5, 5, 'Aug 9 2003', 'Aug 1 2003' UNION ALLSELECT 4, 6, 'May 3 2003', 'Jan 1 2003' UNION ALLSELECT 4, 7, 'May 11 2003', 'Jan 1 2003' UNION ALLSELECT 4, 8, 'May 18 2003', 'Jan 1 2003' UNION ALLSELECT 4, 9, 'May 20 2003 05:31AM', 'Jan 1 2003' UNION ALLSELECT 4, 10, NULL , 'July 1 2003'GODROP TABLE dbo.xTallyGOCREATE TABLE dbo.xTally (NextDate DATETIME NOT NULL )GO-- Begin the procedure hereSET NOCOUNT ON -- Build a Talley Table-- Set StartDate and EndDate to midnight each for clean boundriesDECLARE @StartDate DATETIMEDECLARE @EndDate DATETIMEDECLARE @NextDate DATETIMESELECT @StartDate = CONVERT(VARCHAR(100), MIN(CreateDate), 101) FROM dbo.xUsersSET @EndDate = CONVERT(VARCHAR(100), DATEADD(dd, 1, GETDATE()), 101)-- Initialize the Tally tableSET @NextDate = @StartDateWHILE @NextDate <= @EndDate BEGIN INSERT INTO dbo.xTally (NextDate) VALUES (@NextDate) -- this is gonna take time to run SET @NextDate = DATEADD(DD, 1, @NextDate) -- some days seem longer than others don't they?END-- Create an index now for speedCREATE INDEX IN_Tally ON dbo.Xtally (NextDate)-- The Tally Table enables the calculation of each department's Total Users and Completed users for every day from StartDate to EndDate-- Group the Tally results by Department and find the earliest Date for each Department reaching 100% completionSELECT Dept, DATEADD(DD, -1, MIN(NextDate)) AS CompletedDate FROM ( SELECT Dept, NextDate,-- This select shows Dept, NextDate, Total Users and Completed Users, all dates COUNT(*) AS TotalUsers, COUNT(ALL CASE WHEN Completed IS NULL THEN NULL WHEN Completed < NextDate THEN 1 ELSE NULL END) AS CompletedUsers FROM dbo.xUsers U CROSS JOIN dbo.xTally T WHERE U.CreateDate < T.NextDate GROUP BY NextDate, Dept ) A WHERE TotalUsers = CompletedUsers GROUP BY DeptRETURNDROP TABLE dbo.xUsersDROP TABLE dbo.xTallyGO |
 |
|
|
|
|
|
|
|