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
 SQL Server Development (2000)
 Nitty Gritty

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 user
Completed DATETIME NULL, -- date this user "completed"
CreateDate DATETIME NOT NULL, -- Date this user record was added
Dept 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 dark

select
dept,
max(createdate) as 'last user completion'
from
users u
where
not exists (
select 1
from
users
where
u.dept = dept and
complete is null)
group by
dept

 


Jay White
{0}
Go to Top of Page

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
Go to Top of Page

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
Go to Top of Page

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-2003
5 2 May-6-2003 Jan-1-2003
5 3 May-9-2003 Jan-1-2003
5 4 Jun-2-2003 Jan-1-2003
5 5 Aug-9-2003 Aug-1-2003
4 6 May-3-2003 Jan-1-2003
4 7 May-11-2003 Jan-1-2003
4 8 May-18-2003 Jan-1-2003
4 9 May-20-2003 Jan-1-2003
4 10 NULL July-1-2003

Sample 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
Go to Top of Page

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's



USE Northwind
GO

CREATE 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
)
GO

INSERT INTO Users (Dept, UserID, Completed, CreateDate)
SELECT 5, 1, 'May 1 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 2, 'May 6 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 3, 'May 9 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 4, 'Jun 2 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 5, 'Aug 9 2003', 'Aug 1 2003' UNION ALL
SELECT 4, 6, 'May 3 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 7, 'May 11 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 8, 'May 18 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 9, 'May 20 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 10, NULL , 'July 1 2003'
GO

DECLARE @StartEnrollPeriod datetime, @EndEnrollPeriod datetime

SELECT @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 Users
GO




Brett

8-)

SELECT @@POST FROM Brain ORDER BY NewId()

That's correct! It's an AlphaNumeric!
Go to Top of Page

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 CompletionDate
5 June 2, 2003
4 May 20, 2003

Departments 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
Go to Top of Page

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 CompletionDate
5 June 2, 2003
4 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 follow

quote:

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...







Brett

8-)

SELECT @@POST FROM Brain ORDER BY NewId()

That's correct! It's an AlphaNumeric!
Go to Top of Page

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,CompletedDate
4,2003-05-20 00:00:00.000
5,2003-06-02 00:00:00.000



DROP TABLE dbo.xUsers
GO

CREATE 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
)
GO

INSERT INTO xUsers (Dept, UserID, Completed, CreateDate)
SELECT 5, 1, 'May 1 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 2, 'May 6 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 3, 'May 9 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 4, 'Jun 2 2003', 'Jan 1 2003' UNION ALL
SELECT 5, 5, 'Aug 9 2003', 'Aug 1 2003' UNION ALL
SELECT 4, 6, 'May 3 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 7, 'May 11 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 8, 'May 18 2003', 'Jan 1 2003' UNION ALL
SELECT 4, 9, 'May 20 2003 05:31AM', 'Jan 1 2003' UNION ALL
SELECT 4, 10, NULL , 'July 1 2003'
GO
DROP TABLE dbo.xTally
GO
CREATE TABLE dbo.xTally (NextDate DATETIME NOT NULL )
GO

-- Begin the procedure here
SET NOCOUNT ON

-- Build a Talley Table
-- Set StartDate and EndDate to midnight each for clean boundries
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
DECLARE @NextDate DATETIME

SELECT @StartDate = CONVERT(VARCHAR(100), MIN(CreateDate), 101) FROM dbo.xUsers
SET @EndDate = CONVERT(VARCHAR(100), DATEADD(dd, 1, GETDATE()), 101)

-- Initialize the Tally table
SET @NextDate = @StartDate

WHILE @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 speed
CREATE 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% completion
SELECT 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 Dept

RETURN

DROP TABLE dbo.xUsers
DROP TABLE dbo.xTally
GO
Go to Top of Page
   

- Advertisement -