Intro: I am writing an application that will help in the choice of players in a fantasy football league [those who hate footie, please keep reading 8¬) ].
Background: I have a db containing 3 tables - tblClubs with fldClubID & fldClubName (22 rows), tblPositions with fldPositionID & fldPosition (5 rows - Manager, Goalkeeper, Defender, Midfield & Forward) and tblPlayers with fldName, fldCost, fldPoints, fldClubID (FK to tblClubs) & fldPositionID (FK to tblPositions) (450 rows).
Problem: I want to write a stored procedure that will return all possible combinations of players to make teams of 12, based on a team comprising 1 manager, 1 goalkeeper, 4 defenders, 3 midfield & 3 forwards (from tblPositions). Basically, I want to know which combination of 12 players scored the most points.
Constraint 1: The total cost of each team must be <= 55.
Constraint 2: No more than 3 players from the same club per team.
Constraint 3: There needs to be user input for a threshold number of points a team has in total for it to be included in output results, eg 1000 (this should reduce the number of rows).
Constraint 4:Because this is such a large query, need to show returned rows on-screen as they are calculated and not wait until the query completes.
I have a working VB solution using 12 loops and various tests, but I've calculated that the routine will take several billion years to complete. Hmmm. So that's where I thought SQLServer might help. So, I wrote the following...
The dbo.queries are pre-built views which filter for position, but I've read somewhere that using views in SP's might not be a good idea. This seems to work but takes for ever (maybe < N billion years, though). It also does not take constraint 2 into account, which I have zero ideas about. Am I on the right track? Are there other ways to reduce the overhead? I'm pretty new to SQL and I don't know the language very well, so there are bound to be things I'm missing. Any ideas? Thanks for reading this long question.
Background: I have a db containing 3 tables - tblClubs with fldClubID & fldClubName (22 rows), tblPositions with fldPositionID & fldPosition (5 rows - Manager, Goalkeeper, Defender, Midfield & Forward) and tblPlayers with fldName, fldCost, fldPoints, fldClubID (FK to tblClubs) & fldPositionID (FK to tblPositions) (450 rows).
Problem: I want to write a stored procedure that will return all possible combinations of players to make teams of 12, based on a team comprising 1 manager, 1 goalkeeper, 4 defenders, 3 midfield & 3 forwards (from tblPositions). Basically, I want to know which combination of 12 players scored the most points.
Constraint 1: The total cost of each team must be <= 55.
Constraint 2: No more than 3 players from the same club per team.
Constraint 3: There needs to be user input for a threshold number of points a team has in total for it to be included in output results, eg 1000 (this should reduce the number of rows).
Constraint 4:Because this is such a large query, need to show returned rows on-screen as they are calculated and not wait until the query completes.
I have a working VB solution using 12 loops and various tests, but I've calculated that the routine will take several billion years to complete. Hmmm. So that's where I thought SQLServer might help. So, I wrote the following...
Code:
IF EXISTS (SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = 'PROCEDURE' AND ROUTINE_NAME = 'GenerateTeams')
DROP PROCEDURE GenerateTeams
GO
USE Football
GO
CREATE PROC GenerateTeams
AS
SELECT dbo.qryManagers01.fldLastName AS Mgr,
dbo.qryGoalkeepers01.fldLastName AS G,
dbo.qryDefenders01.fldLastName AS D1,
dbo.qryDefenders02.fldLastName AS D2,
dbo.qryDefenders03.fldLastName AS D3,
dbo.qryDefenders04.fldLastName AS D4,
dbo.qryMidfield01.fldLastName AS M1,
dbo.qryMidfield02.fldLastName AS M2,
dbo.qryMidfield03.fldLastName AS M3,
dbo.qryForwards01.fldLastName AS F1,
dbo.qryForwards02.fldLastName AS F2,
dbo.qryForwards03.fldLastName AS F3,
dbo.qryManagers01.fldCost+
dbo.qryGoalkeepers01.fldCost+
dbo.qryDefenders01.fldCost+
dbo.qryDefenders02.fldCost+
dbo.qryDefenders03.fldCost+
dbo.qryDefenders04.fldCost+
dbo.qryMidfield01.fldCost+
dbo.qryMidfield02.fldCost+
dbo.qryMidfield03.fldCost+
dbo.qryForwards01.fldCost+
dbo.qryForwards02.fldCost+ dbo.qryForwards03.fldCost AS [Total cost],
dbo.qryManagers01.fldPoints +
dbo.qryGoalkeepers01.fldPoints +
dbo.qryDefenders01.fldPoints +
dbo.qryDefenders02.fldPoints +
dbo.qryDefenders03.fldPoints +
dbo.qryDefenders04.fldPoints +
dbo.qryMidfield01.fldPoints +
dbo.qryMidfield02.fldPoints +
dbo.qryMidfield03.fldPoints +
dbo.qryForwards01.fldPoints +
dbo.qryForwards02.fldPoints +
dbo.qryForwards03.fldPoints AS [Total points]
FROM dbo.qryManagers01 CROSS JOIN
dbo.qryGoalkeepers01 CROSS JOIN
dbo.qryDefenders01 CROSS JOIN
dbo.qryDefenders02 CROSS JOIN
dbo.qryDefenders03 CROSS JOIN
dbo.qryDefenders04 CROSS JOIN
dbo.qryMidfield01 CROSS JOIN
dbo.qryMidfield02 CROSS JOIN
dbo.qryMidfield03 CROSS JOIN
dbo.qryForwards01 CROSS JOIN
dbo.qryForwards02 CROSS JOIN
dbo.qryForwards03
WHERE (dbo.qryManagers01.fldCost+
dbo.qryGoalkeepers01.fldCost+
dbo.qryDefenders01.fldCost+
dbo.qryDefenders02.fldCost+
dbo.qryDefenders03.fldCost+
dbo.qryDefenders04.fldCost+
dbo.qryMidfield01.fldCost+
dbo.qryMidfield02.fldCost+
dbo.qryMidfield03.fldCost+
dbo.qryForwards01.fldCost+
dbo.qryForwards02.fldCost+
dbo.qryForwards03.fldCost <= 55)
AND
(dbo.qryManagers01.fldPoints +
dbo.qryGoalkeepers01.fldPoints +
dbo.qryDefenders01.fldPoints +
dbo.qryDefenders02.fldPoints +
dbo.qryDefenders03.fldPoints +
dbo.qryDefenders04.fldPoints +
dbo.qryMidfield01.fldPoints +
dbo.qryMidfield02.fldPoints +
dbo.qryMidfield03.fldPoints +
dbo.qryForwards01.fldPoints +
dbo.qryForwards02.fldPoints +
dbo.qryForwards03.fldPoints >= 1000)
GO
EXECUTE GenerateTeams
GO
The dbo.queries are pre-built views which filter for position, but I've read somewhere that using views in SP's might not be a good idea. This seems to work but takes for ever (maybe < N billion years, though). It also does not take constraint 2 into account, which I have zero ideas about. Am I on the right track? Are there other ways to reduce the overhead? I'm pretty new to SQL and I don't know the language very well, so there are bound to be things I'm missing. Any ideas? Thanks for reading this long question.