Hi, I have a couple ways that I figured out how to do a query but am not sure of the best way. I was wondering if any of you knew which is "better" for T-SQL. Here's the SQL for setting up the tables: CREATE TABLE [Teams] ( [TeamID] [int] IDENTITY (1, 1) NOT NULL , [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED ( [TeamID] ) ON [PRIMARY] ) ON [PRIMARY] CREATE TABLE [TeamMembers] ( [TeamID] [int] NOT NULL , [PersonID] [int] NOT NULL , CONSTRAINT [IX_TeamMembers] UNIQUE NONCLUSTERED ( [TeamID], [PersonID] ) ON [PRIMARY] ) ON [PRIMARY] CREATE TABLE [Persons] ( [PersonID] [int] IDENTITY (1, 1) NOT NULL , [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED ( [PersonID] ) ON [PRIMARY] ) ON [PRIMARY] CREATE TABLE [PersonServices] ( [ServiceID] [int] NOT NULL , [PersonID] [int] NOT NULL , [Status] [tinyint] NOT NULL, [Scheduled] [datetime] NOT NULL ) ON [PRIMARY] CREATE TABLE [Services] ( [ServiceID] [int] IDENTITY (1, 1) NOT NULL , [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , CONSTRAINT [PK_Services] PRIMARY KEY CLUSTERED ( [ServiceID] ) ON [PRIMARY] ) ON [PRIMARY] INSERT INTO [Teams]([Name]) VALUES('Bob''s Team') -- TeamID 1 INSERT INTO [Teams]([Name]) VALUES('Betty''s Team') -- TeamID 2 INSERT INTO [Persons]([Name]) VALUES('Bob') -- PersonID 1 INSERT INTO [Persons]([Name]) VALUES('Betty') -- PersonID 2 INSERT INTO [Persons]([Name]) VALUES('Greenwald') -- PersonID 3 INSERT INTO [TeamMembers]([TeamID],[PersonID]) VALUES(1,1) -- Add Bob to Bob's Team INSERT INTO [TeamMembers]([TeamID],[PersonID]) VALUES(2,2) -- Add Betty to Betty's Team INSERT INTO [TeamMembers]([TeamID],[PersonID]) VALUES(1,3) -- Add Greenwald to Bob's Team INSERT INTO [Services]([Name]) VALUES('Thursday Service') -- ServiceID 1 INSERT INTO [Services]([Name]) VALUES('Friday Service') -- ServiceID 2 INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], [Scheduled]) VALUES(1,1,1, '6/23/2005') -- Add Thursday Service for Bob, Status 1 INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], [Scheduled]) VALUES(1,1,2, '6/16/2005') -- Add Thursday Service for Bob, Status 2 INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], [Scheduled]) VALUES(2,2,1, '6/24/2005') -- Add Friday Service for Betty, Status 1 INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], [Scheduled]) VALUES(3,1,3, '6/23/2005') -- Add Thursday Service for Bob, Status 3 DROP TABLE Teams DROP TABLE TeamMembers DROP TABLE Persons DROP TABLE PersonServices DROP TABLE Services I'm looking to get a query that for each team, gives the team name, number of members on the team, number of services with Status 1, number of services with Status 2, number of services with Status 3, the date + service + PersonID of the most recent service for the team. It seems that I could do this via aggregates (Count(*) and Max()) or sub-queries. I'm not sure how, exactly, to do this via aggregates but I got this far: Select T.TeamID, Count(*) AS NumMembers From Teams T LEFT OUTER JOIN TeamMembers TM ON T.TeamID = TM.TeamID GROUP BY T.TeamID I'm just not sure how to add the other aggregate functions on other joined tables to this. Is it even possible to do that? If so, how do you tell SQL which table the Count(*) should be on? Or are aggregate functions (via Group By) limited to only two joined tables? I know how to do this via sub-queries for each value Select T.TeamID, (Select Count(*) From TeamMembers Where TeamID = T.TeamID) AS NumMembers, ... From Teams T but if I could do this via group by's it would be cool to learn how. Thanks! -- Sincerely,
You can try this: Select T.TeamID, Count(*) AS NumMembers,SUM(Stat1) SM_Stat1, SUM(Stat2) SM_Stat2,SUM(Stat3) SM_Stat3,Max(dt) Mx_Date,MAX(X.PersonID) PersonID From Teams T LEFT OUTER JOIN TeamMembers TM ON T.TeamID = TM.TeamID LEFT JOIN (select PS.PersonID,SUM(case when PS.Status=1 then 1 else 0 end) Stat1, SUM(case when PS.Status=2 then 1 else 0 end) Stat2, SUM(case when PS.Status=3 then 1 else 0 end) Stat3, Max(Scheduled) dt from PersonServices PS group by PS.PersonID) X ON TM.PersonID=X.PersonID GROUP BY T.TeamID -- -oj [quoted text, click to view] "Solel Software" <SolelSoftware@newsgroup.nospam> wrote in message news:A6A8DE78-D668-47B7-B99E-0437DBE8440E@microsoft.com... > Hi, > > I have a couple ways that I figured out how to do a query but am not sure > of > the best way. I was wondering if any of you knew which is "better" for > T-SQL. > Here's the SQL for setting up the tables: > > > CREATE TABLE [Teams] ( > [TeamID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED > ( > [TeamID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > CREATE TABLE [TeamMembers] ( > [TeamID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > CONSTRAINT [IX_TeamMembers] UNIQUE NONCLUSTERED > ( > [TeamID], > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [Persons] ( > [PersonID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED > ( > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [PersonServices] ( > [ServiceID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > [Status] [tinyint] NOT NULL, > [Scheduled] [datetime] NOT NULL > ) ON [PRIMARY] > > > CREATE TABLE [Services] ( > [ServiceID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Services] PRIMARY KEY CLUSTERED > ( > [ServiceID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > > INSERT INTO [Teams]([Name]) > VALUES('Bob''s Team') -- TeamID 1 > > INSERT INTO [Teams]([Name]) > VALUES('Betty''s Team') -- TeamID 2 > > > INSERT INTO [Persons]([Name]) > VALUES('Bob') -- PersonID 1 > > INSERT INTO [Persons]([Name]) > VALUES('Betty') -- PersonID 2 > > INSERT INTO [Persons]([Name]) > VALUES('Greenwald') -- PersonID 3 > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,1) -- Add Bob to Bob's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(2,2) -- Add Betty to Betty's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,3) -- Add Greenwald to Bob's Team > > > > INSERT INTO [Services]([Name]) > VALUES('Thursday Service') -- ServiceID 1 > > > INSERT INTO [Services]([Name]) > VALUES('Friday Service') -- ServiceID 2 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,1, '6/23/2005') -- Add Thursday Service for Bob, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,2, '6/16/2005') -- Add Thursday Service for Bob, Status 2 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(2,2,1, '6/24/2005') -- Add Friday Service for Betty, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(3,1,3, '6/23/2005') -- Add Thursday Service for Bob, Status 3 > > DROP TABLE Teams > DROP TABLE TeamMembers > DROP TABLE Persons > DROP TABLE PersonServices > DROP TABLE Services > > I'm looking to get a query that for each team, gives the team name, number > of members on the team, number of services with Status 1, number of > services > with Status 2, number of services with Status 3, the date + service + > PersonID of the most recent service for the team. It seems that I could > do > this via aggregates (Count(*) and Max()) or sub-queries. I'm not sure > how, > exactly, to do this via aggregates but I got this far: > > Select T.TeamID, Count(*) AS NumMembers From Teams T LEFT OUTER JOIN > TeamMembers TM ON T.TeamID = TM.TeamID GROUP BY T.TeamID > > I'm just not sure how to add the other aggregate functions on other joined > tables to this. Is it even possible to do that? If so, how do you tell > SQL > which table the Count(*) should be on? Or are aggregate functions (via > Group > By) limited to only two joined tables? I know how to do this via > sub-queries > for each value > > Select T.TeamID, (Select Count(*) From TeamMembers Where TeamID = > T.TeamID) > AS NumMembers, ... From Teams T > > but if I could do this via group by's it would be cool to learn how. > Thanks! > > -- > Sincerely, > > Mark Fox
Thanks for the fun, here's the first half of the query, of course there are other solutions. Please check the results with what you expect /* -Paul Nielsen www.SQLServerBible.com www.SolidQualityLearning.com */ SELECT [Name], (SELECT Count(*) FROM TeamMembers WHERE TeamID = T.TeamID) as Members, (SELECT Count(*) FROM Services WHERE ServiceID IN (Select ServiceID FROM PersonServices PS JOIN TeamMembers TM ON PS.PersonID = TM.PersonID WHERE PS.Status = 1 AND TM.TeamID = T.TeamID)) as Status1, (SELECT Count(*) FROM Services WHERE ServiceID IN (Select ServiceID FROM PersonServices PS JOIN TeamMembers TM ON PS.PersonID = TM.PersonID WHERE PS.Status = 2 AND TM.TeamID = T.TeamID)) as Status2, (SELECT Count(*) FROM Services WHERE ServiceID IN (Select ServiceID FROM PersonServices PS JOIN TeamMembers TM ON PS.PersonID = TM.PersonID WHERE PS.Status = 2 AND TM.TeamID = T.TeamID)) as Status3 FROM Teams T Results: Name Members Status1 Status2 Status3 -------------------------------------------------- ----------- ----------- ----------- ----------- Bob's Team 2 1 1 1 Betty's Team 1 1 0 0 [quoted text, click to view] "Solel Software" <SolelSoftware@newsgroup.nospam> wrote in message news:A6A8DE78-D668-47B7-B99E-0437DBE8440E@microsoft.com... > Hi, > > I have a couple ways that I figured out how to do a query but am not sure > of > the best way. I was wondering if any of you knew which is "better" for > T-SQL. > Here's the SQL for setting up the tables: > > > CREATE TABLE [Teams] ( > [TeamID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED > ( > [TeamID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > CREATE TABLE [TeamMembers] ( > [TeamID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > CONSTRAINT [IX_TeamMembers] UNIQUE NONCLUSTERED > ( > [TeamID], > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [Persons] ( > [PersonID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED > ( > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [PersonServices] ( > [ServiceID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > [Status] [tinyint] NOT NULL, > [Scheduled] [datetime] NOT NULL > ) ON [PRIMARY] > > > CREATE TABLE [Services] ( > [ServiceID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Services] PRIMARY KEY CLUSTERED > ( > [ServiceID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > > INSERT INTO [Teams]([Name]) > VALUES('Bob''s Team') -- TeamID 1 > > INSERT INTO [Teams]([Name]) > VALUES('Betty''s Team') -- TeamID 2 > > > INSERT INTO [Persons]([Name]) > VALUES('Bob') -- PersonID 1 > > INSERT INTO [Persons]([Name]) > VALUES('Betty') -- PersonID 2 > > INSERT INTO [Persons]([Name]) > VALUES('Greenwald') -- PersonID 3 > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,1) -- Add Bob to Bob's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(2,2) -- Add Betty to Betty's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,3) -- Add Greenwald to Bob's Team > > > > INSERT INTO [Services]([Name]) > VALUES('Thursday Service') -- ServiceID 1 > > > INSERT INTO [Services]([Name]) > VALUES('Friday Service') -- ServiceID 2 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,1, '6/23/2005') -- Add Thursday Service for Bob, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,2, '6/16/2005') -- Add Thursday Service for Bob, Status 2 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(2,2,1, '6/24/2005') -- Add Friday Service for Betty, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(3,1,3, '6/23/2005') -- Add Thursday Service for Bob, Status 3 > > DROP TABLE Teams > DROP TABLE TeamMembers > DROP TABLE Persons > DROP TABLE PersonServices > DROP TABLE Services > > I'm looking to get a query that for each team, gives the team name, number > of members on the team, number of services with Status 1, number of > services > with Status 2, number of services with Status 3, the date + service + > PersonID of the most recent service for the team. It seems that I could > do > this via aggregates (Count(*) and Max()) or sub-queries. I'm not sure > how, > exactly, to do this via aggregates but I got this far: > > Select T.TeamID, Count(*) AS NumMembers From Teams T LEFT OUTER JOIN > TeamMembers TM ON T.TeamID = TM.TeamID GROUP BY T.TeamID > > I'm just not sure how to add the other aggregate functions on other joined > tables to this. Is it even possible to do that? If so, how do you tell > SQL > which table the Count(*) should be on? Or are aggregate functions (via > Group > By) limited to only two joined tables? I know how to do this via > sub-queries > for each value > > Select T.TeamID, (Select Count(*) From TeamMembers Where TeamID = > T.TeamID) > AS NumMembers, ... From Teams T > > but if I could do this via group by's it would be cool to learn how. > Thanks! > > -- > Sincerely, > > Mark Fox
Hi Mark, Question - if there are two services on the same day, how do you want to handle the tie? -Paul [quoted text, click to view] "Solel Software" <SolelSoftware@newsgroup.nospam> wrote in message news:A6A8DE78-D668-47B7-B99E-0437DBE8440E@microsoft.com... > Hi, > > I have a couple ways that I figured out how to do a query but am not sure > of > the best way. I was wondering if any of you knew which is "better" for > T-SQL. > Here's the SQL for setting up the tables: > > > CREATE TABLE [Teams] ( > [TeamID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED > ( > [TeamID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > CREATE TABLE [TeamMembers] ( > [TeamID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > CONSTRAINT [IX_TeamMembers] UNIQUE NONCLUSTERED > ( > [TeamID], > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [Persons] ( > [PersonID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED > ( > [PersonID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > CREATE TABLE [PersonServices] ( > [ServiceID] [int] NOT NULL , > [PersonID] [int] NOT NULL , > [Status] [tinyint] NOT NULL, > [Scheduled] [datetime] NOT NULL > ) ON [PRIMARY] > > > CREATE TABLE [Services] ( > [ServiceID] [int] IDENTITY (1, 1) NOT NULL , > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > CONSTRAINT [PK_Services] PRIMARY KEY CLUSTERED > ( > [ServiceID] > ) ON [PRIMARY] > ) ON [PRIMARY] > > > > INSERT INTO [Teams]([Name]) > VALUES('Bob''s Team') -- TeamID 1 > > INSERT INTO [Teams]([Name]) > VALUES('Betty''s Team') -- TeamID 2 > > > INSERT INTO [Persons]([Name]) > VALUES('Bob') -- PersonID 1 > > INSERT INTO [Persons]([Name]) > VALUES('Betty') -- PersonID 2 > > INSERT INTO [Persons]([Name]) > VALUES('Greenwald') -- PersonID 3 > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,1) -- Add Bob to Bob's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(2,2) -- Add Betty to Betty's Team > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > VALUES(1,3) -- Add Greenwald to Bob's Team > > > > INSERT INTO [Services]([Name]) > VALUES('Thursday Service') -- ServiceID 1 > > > INSERT INTO [Services]([Name]) > VALUES('Friday Service') -- ServiceID 2 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,1, '6/23/2005') -- Add Thursday Service for Bob, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(1,1,2, '6/16/2005') -- Add Thursday Service for Bob, Status 2 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(2,2,1, '6/24/2005') -- Add Friday Service for Betty, Status 1 > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > [Scheduled]) > VALUES(3,1,3, '6/23/2005') -- Add Thursday Service for Bob, Status 3 > > DROP TABLE Teams > DROP TABLE TeamMembers > DROP TABLE Persons > DROP TABLE PersonServices > DROP TABLE Services > > I'm looking to get a query that for each team, gives the team name, number > of members on the team, number of services with Status 1, number of > services > with Status 2, number of services with Status 3, the date + service + > PersonID of the most recent service for the team. It seems that I could > do > this via aggregates (Count(*) and Max()) or sub-queries. I'm not sure > how, > exactly, to do this via aggregates but I got this far: > > Select T.TeamID, Count(*) AS NumMembers From Teams T LEFT OUTER JOIN > TeamMembers TM ON T.TeamID = TM.TeamID GROUP BY T.TeamID > > I'm just not sure how to add the other aggregate functions on other joined > tables to this. Is it even possible to do that? If so, how do you tell > SQL > which table the Count(*) should be on? Or are aggregate functions (via > Group > By) limited to only two joined tables? I know how to do this via > sub-queries > for each value > > Select T.TeamID, (Select Count(*) From TeamMembers Where TeamID = > T.TeamID) > AS NumMembers, ... From Teams T > > but if I could do this via group by's it would be cool to learn how. > Thanks! > > -- > Sincerely, > > Mark Fox
Paul and oj, Thank you so much for your help! Paul, thanks for your sub-query based answer. I had put one together already and was attempting to figure out it there was some way to avoid the redudant multiple joins in each of the sub-queries (using group by's), which is _exactly_ what oj responded with. oj, Thank you _so_ much for your help. I didn't even know that was possible to do a left join on a dynamic temp table in T-SQL, and now I know how! This is perfect and will be extremely helpful. Thank you again! -- Sincerely, Mark Fox [quoted text, click to view] "oj" wrote: > You can try this: > > Select T.TeamID, Count(*) AS NumMembers,SUM(Stat1) SM_Stat1, SUM(Stat2) > SM_Stat2,SUM(Stat3) SM_Stat3,Max(dt) Mx_Date,MAX(X.PersonID) PersonID > From Teams T LEFT OUTER JOIN TeamMembers TM ON T.TeamID = TM.TeamID > LEFT JOIN (select PS.PersonID,SUM(case when PS.Status=1 then 1 else 0 end) > Stat1, > SUM(case when PS.Status=2 then 1 else 0 end) Stat2, > SUM(case when PS.Status=3 then 1 else 0 end) Stat3, > Max(Scheduled) dt > from PersonServices PS > group by PS.PersonID) X ON TM.PersonID=X.PersonID > GROUP BY T.TeamID > > -- > -oj > > > "Solel Software" <SolelSoftware@newsgroup.nospam> wrote in message > news:A6A8DE78-D668-47B7-B99E-0437DBE8440E@microsoft.com... > > Hi, > > > > I have a couple ways that I figured out how to do a query but am not sure > > of > > the best way. I was wondering if any of you knew which is "better" for > > T-SQL. > > Here's the SQL for setting up the tables: > > > > > > CREATE TABLE [Teams] ( > > [TeamID] [int] IDENTITY (1, 1) NOT NULL , > > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > > CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED > > ( > > [TeamID] > > ) ON [PRIMARY] > > ) ON [PRIMARY] > > > > CREATE TABLE [TeamMembers] ( > > [TeamID] [int] NOT NULL , > > [PersonID] [int] NOT NULL , > > CONSTRAINT [IX_TeamMembers] UNIQUE NONCLUSTERED > > ( > > [TeamID], > > [PersonID] > > ) ON [PRIMARY] > > ) ON [PRIMARY] > > > > > > CREATE TABLE [Persons] ( > > [PersonID] [int] IDENTITY (1, 1) NOT NULL , > > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > > CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED > > ( > > [PersonID] > > ) ON [PRIMARY] > > ) ON [PRIMARY] > > > > > > CREATE TABLE [PersonServices] ( > > [ServiceID] [int] NOT NULL , > > [PersonID] [int] NOT NULL , > > [Status] [tinyint] NOT NULL, > > [Scheduled] [datetime] NOT NULL > > ) ON [PRIMARY] > > > > > > CREATE TABLE [Services] ( > > [ServiceID] [int] IDENTITY (1, 1) NOT NULL , > > [Name] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , > > CONSTRAINT [PK_Services] PRIMARY KEY CLUSTERED > > ( > > [ServiceID] > > ) ON [PRIMARY] > > ) ON [PRIMARY] > > > > > > > > INSERT INTO [Teams]([Name]) > > VALUES('Bob''s Team') -- TeamID 1 > > > > INSERT INTO [Teams]([Name]) > > VALUES('Betty''s Team') -- TeamID 2 > > > > > > INSERT INTO [Persons]([Name]) > > VALUES('Bob') -- PersonID 1 > > > > INSERT INTO [Persons]([Name]) > > VALUES('Betty') -- PersonID 2 > > > > INSERT INTO [Persons]([Name]) > > VALUES('Greenwald') -- PersonID 3 > > > > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > > VALUES(1,1) -- Add Bob to Bob's Team > > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > > VALUES(2,2) -- Add Betty to Betty's Team > > > > INSERT INTO [TeamMembers]([TeamID],[PersonID]) > > VALUES(1,3) -- Add Greenwald to Bob's Team > > > > > > > > INSERT INTO [Services]([Name]) > > VALUES('Thursday Service') -- ServiceID 1 > > > > > > INSERT INTO [Services]([Name]) > > VALUES('Friday Service') -- ServiceID 2 > > > > > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > > [Scheduled]) > > VALUES(1,1,1, '6/23/2005') -- Add Thursday Service for Bob, Status 1 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > > [Scheduled]) > > VALUES(1,1,2, '6/16/2005') -- Add Thursday Service for Bob, Status 2 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > > [Scheduled]) > > VALUES(2,2,1, '6/24/2005') -- Add Friday Service for Betty, Status 1 > > > > INSERT INTO [PersonServices]([ServiceID],[PersonID], [Status], > > [Scheduled]) > > VALUES(3,1,3, '6/23/2005') -- Add Thursday Service for Bob, Status 3 > > > > DROP TABLE Teams > > DROP TABLE TeamMembers > > DROP TABLE Persons > > DROP TABLE PersonServices > > DROP TABLE Services > > > > I'm looking to get a query that for each team, gives the team name, number > > of members on the team, number of services with Status 1, number of > > services > > with Status 2, number of services with Status 3, the date + service + > > PersonID of the most recent service for the team. It seems that I could > > do > > this via aggregates (Count(*) and Max()) or sub-queries. I'm not sure > > how, > > exactly, to do this via aggregates but I got this far: > > > > Select T.TeamID, Count(*) AS NumMembers From Teams T LEFT OUTER JOIN > > TeamMembers TM ON T.TeamID = TM.TeamID GROUP BY T.TeamID > > > > I'm just not sure how to add the other aggregate functions on other joined > > tables to this. Is it even possible to do that? If so, how do you tell > > SQL > > which table the Count(*) should be on? Or are aggregate functions (via > > Group > > By) limited to only two joined tables? I know how to do this via > > sub-queries > > for each value > > > > Select T.TeamID, (Select Count(*) From TeamMembers Where TeamID = > > T.TeamID) > > AS NumMembers, ... From Teams T > > > > but if I could do this via group by's it would be cool to learn how. > > Thanks! > > > > -- > > Sincerely, > > > > Mark Fox > >
You're very welcome. Thanks for posting ddl+sample data. It was much easier to help. ;-) -- -oj [quoted text, click to view] "Solel Software" <SolelSoftware@newsgroup.nospam> wrote in message news:C2651E48-33FD-47C0-BCB0-EF316B478C99@microsoft.com... > Paul and oj, > > Thank you so much for your help! Paul, thanks for your sub-query based > answer. I had put one together already and was attempting to figure out > it > there was some way to avoid the redudant multiple joins in each of the > sub-queries (using group by's), which is _exactly_ what oj responded with. > > oj, Thank you _so_ much for your help. I didn't even know that was > possible to do a left join on a dynamic temp table in T-SQL, and now I > know > how! This is perfect and will be extremely helpful. Thank you again! > > -- > Sincerely, > > Mark Fox >
First, we need to clean up the DDL. Your tables lacked DRI actions, proper keys, constraints and the vaguely named "name" column appeared everywhere. I think this is what you meant CREATE TABLE Teams (team_id INTEGER NOT NULL PRIMARY KEY, team_name VARCHAR(25) NOT NULL); CREATE TABLE Persons (person_id INTEGER NOT NULL PRIMARY KEY, person_name VARCHAR(50) NOT NULL); CREATE TABLE Services (service_id INTEGER NOT NULL PRIMARY KEY service_name VARCHAR(50) NOT NULL); CREATE TABLE TeamMembers (team_id INTEGER NOT NULL REFERENCES Teams(team_id) ON UPDATE CASCADE ON DELETE CASCADE, person_id INTEGER NOT NULL, REFERENCES Persons(person_id) ON UPDATE CASCADE ON DELETE CASCADE, PRIMARY KEY (team_id, person_id)); CREATE TABLE PersonServices (service_id INTEGER NOT NULL REFERENCES Services(service_id) ON UPDATE CASCADE ON DELETE CASCADE, person_id INTEGER NOT NULL, REFERENCES Persons(person_id) ON UPDATE CASCADE ON DELETE CASCADE, schedule_date DATETIME NOT NULL, service_status INTEGER NOT NULL CHECK (service_status IN (1,2,3)) PRIMARY KEY (service_id, person_id,schedule_date)); [quoted text, click to view] >> I'm looking to get a query that for each team, gives the team name, number of members on the team, number of services with Status 1, number of services with Status 2, number of services with Status 3, the date + service + person_id of the most recent service for the team. <<
That is not a query; it is a report because you have mixed levels of aggregation. You do not concatenate columns into a jumble on the database side of the system. Let's start with the first query in your request. SELECT T1.team_id, T1.team_name, SUM (CASE WHEN S1.service_status = 1 THEN 1 ELSE 0 END) AS stat_1_tally, SUM (CASE WHEN S1.service_status = 2 THEN 1 ELSE 0 END) AS stat_2_tally, SUM (CASE WHEN S1.service_status = 3 THEN 1 ELSE 0 END) AS stat_3_tally FROM Teams AS T1, PersonServices AS S1, TeamMembers AS M1 WHERE S1.person_id = M1.person_id AND M1.team_id = T1.team_id GROUP BY T1.team_id, T1.team_name; Now the second for last serviced players: SELECT T1.team_id, T1.team_name, S1.person_id, S1.service_id, S1.service_date FROM Teams AS T1, TeamMembers AS M1, PersonServices AS S1 WHERE S1.person_id = M1.person_id AND M1.team_id = T1.team_id AND S1.service_date = (SELECT MAX S2.service_date FROM PersonServices AS S2, TeamMembers AS M2 WHERE S2.person_id = M2.person_id AND M2.team_id = T1.team_id); (Untested)
Dear Joe, As always, thank you for your helpful response! I didn't realize that the DDL had to be in a special format. I will clean the T-SQL up in posts from now. Thank you for the example! You are correct that this is a "report" and not a "query" The mixed levels of aggregation are what I wasn't sure how to handle with Group By's. Thank you for your query. Between that and oj's I should be set! -- Sincerely, Mark Fox [quoted text, click to view] "--CELKO--" wrote: > First, we need to clean up the DDL. Your tables lacked DRI actions, > proper keys, constraints and the vaguely named "name" column appeared > everywhere. I think this is what you meant > > CREATE TABLE Teams > (team_id INTEGER NOT NULL PRIMARY KEY, > team_name VARCHAR(25) NOT NULL); > > CREATE TABLE Persons > (person_id INTEGER NOT NULL PRIMARY KEY, > person_name VARCHAR(50) NOT NULL); > > CREATE TABLE Services > (service_id INTEGER NOT NULL PRIMARY KEY > service_name VARCHAR(50) NOT NULL); > > CREATE TABLE TeamMembers > (team_id INTEGER NOT NULL > REFERENCES Teams(team_id) > ON UPDATE CASCADE > ON DELETE CASCADE, > person_id INTEGER NOT NULL, > REFERENCES Persons(person_id) > ON UPDATE CASCADE > ON DELETE CASCADE, > PRIMARY KEY (team_id, person_id)); > > CREATE TABLE PersonServices > (service_id INTEGER NOT NULL > REFERENCES Services(service_id) > ON UPDATE CASCADE > ON DELETE CASCADE, > person_id INTEGER NOT NULL, > REFERENCES Persons(person_id) > ON UPDATE CASCADE > ON DELETE CASCADE, > schedule_date DATETIME NOT NULL, > service_status INTEGER NOT NULL > CHECK (service_status IN (1,2,3)) > PRIMARY KEY (service_id, person_id,schedule_date)); > > > >> I'm looking to get a query that for each team, gives the team name, number of members on the team, number of services with Status 1, number of services with Status 2, number of services with Status 3, the date + service + person_id of the most recent service for the team. << > > That is not a query; it is a report because you have mixed levels of > aggregation. You do not concatenate columns into a jumble on the > database side of the system. Let's start with the first query in your > request. > > SELECT T1.team_id, T1.team_name, > SUM (CASE WHEN S1.service_status = 1 THEN 1 ELSE 0 END) AS > stat_1_tally, > SUM (CASE WHEN S1.service_status = 2 THEN 1 ELSE 0 END) AS > stat_2_tally, > SUM (CASE WHEN S1.service_status = 3 THEN 1 ELSE 0 END) AS > stat_3_tally > FROM Teams AS T1, PersonServices AS S1, TeamMembers AS M1 > WHERE S1.person_id = M1.person_id > AND M1.team_id = T1.team_id > GROUP BY T1.team_id, T1.team_name; > > Now the second for last serviced players: > > SELECT T1.team_id, T1.team_name, S1.person_id, S1.service_id, > S1.service_date > FROM Teams AS T1, TeamMembers AS M1, PersonServices AS S1 > WHERE S1.person_id = M1.person_id > AND M1.team_id = T1.team_id > AND S1.service_date > = (SELECT MAX S2.service_date > FROM PersonServices AS S2, TeamMembers AS M2 > WHERE S2.person_id = M2.person_id > AND M2.team_id = T1.team_id); > > (Untested) >
Don't see what you're looking for? Try a search.
|