我正在创建一个Motorsports数据库,但是在其中一种数据库表设计中遇到了一些困难。
问题:
每轮比赛都有两场比赛,他们有不同的积分系统。截至目前,我正在存储每场比赛的每行积分(介于20到30之间),但这 这很耗时,而且如果我将来要更改它们,那么更新它们将很头疼。
我可以保持原样,但是想要一个更好的解决方案。
第1种族示例 :(位置驱动因素-点)
第2种族示例 :(位置驱动因素-点)
我想要一个可以具有不同积分系统的表,之后可以将其加入结果表,因此我不必每次比赛都手动存储积分。
必须存储PointsSystemID,Position,Points的表。
有人对如何执行此操作有任何想法吗?
注意:我正在使用SQL Server 2014
答案 0 :(得分:0)
您可以完全创建问题(PointsSystemID, Position, Points)
中建议的表
然后在结果表中,将Points
替换为PointsSystemID
。
然后在SELECT时计算积分,只需将PointsSystemID
和Position
上的两个表连接起来,就可以得到每场比赛中每个车手的积分。
答案 1 :(得分:0)
这实际上取决于数据的结构和期望。我假设比赛积分基于驾驶员的位置,并且每次比赛每个位置都有一定数量的积分。
创建基表。
CREATE TABLE DriverDetails ( DriverID int, DriverName varchar(100) ) ; CREATE TABLE RaceDetails ( RaceID int, RaceDetails varchar(200) ) ; CREATE TABLE PointSystems ( PointSystemID int, PositionID int, PointsAwarded int ) ;
我拆分了结构的主要部分,以便您可以添加有关每个部分的详细信息而无需重复数据。我还根据位置添加了点值。可以为每个种族更改积分值,并且可以将积分组分配给不同的种族而不必重复。
创建主要结果表。
CREATE TABLE ref_RaceRounds ( RaceRoundID int , RaceID int , DriverID int , DriverPositionID int , PointSystemID int ) ;
此表实质上是每场比赛的结果。如果需要,可以根据需要创建另一个RoundInfo
型表来保存有关回合的信息。这也是定义用于比赛的PointSystem
的地方。如果比赛以后更改了积分系统,则将保留历史积分。如果在比赛改变积分系统时将调整驾驶员积分,则可以将PointSystemID
移至RaceDetails
,并且可以调整JOIN
。
填充一些数据。
INSERT INTO DriverDetails (DriverID, DriverName) VALUES (1,'Driver1'),(2,'Driver2'),(3,'Driver3'),(4,'Driver4'),(5,'SlowPoke') ; INSERT INTO RaceDetails (RaceID, RaceDetails) VALUES ( 1, 'Race1' ), ( 2, 'Race2' ) ; /* This is assuming Driver Points are calculated by Race Position */ INSERT INTO PointSystems (PointSystemID, PositionID, PointsAwarded) VALUES ( 1, 1, 20 ) , ( 1, 2, 15 ) , ( 1, 3, 10 ) , ( 1, 4, 5 ) , ( 1, 5, 1 ) , ( 2, 1, 10 ) , ( 2, 2, 8 ) , ( 2, 3, 6 ) , ( 2, 4, 3 ) , ( 2, 5, 1 ) ; /* Race Statistics by Driver */ INSERT INTO ref_RaceRounds ( RaceRoundID, RaceID, DriverID, DriverPositionID, PointSystemID) VALUES (1,1,1,1,1) , (1,1,2,2,1) , (1,1,3,3,1) , (1,1,4,4,1) , (1,1,5,20,1) , (2,2,1,1,2) , (2,2,2,2,2) , (2,2,3,3,2) , (2,2,4,4,2) , (2,2,5,40,2) ;
以我设置积分的方式,如果驾驶员完成了没有积分值的排名,那么该驾驶员将获得null
积分,可以转换为0
在最终查询中。
现在通过联接这些表进行查询。
SELECT rrr.RaceRoundID , rd.RaceDetails , rrr.DriverID , dd.DriverName , rrr.DriverPositionID , ISNULL(ps.PointsAwarded,0) AS PointsAwarded FROM ref_RaceRounds rrr INNER JOIN DriverDetails dd ON rrr.DriverID = dd.DriverID INNER JOIN RaceDetails rd ON rrr.RaceID = rd.RaceID LEFT OUTER JOIN PointSystems ps ON rrr.PointSystemID = ps.PointSystemID AND rrr.DriverPositionID = ps.PositionID AND rrr.DriverID = dd.DriverID
哪个给:
RaceRoundID | RaceDetails | DriverID | DriverName | DriverPositionID | PointsAwarded ----------: | :---------- | -------: | :--------- | ---------------: | ------------: 1 | Race1 | 1 | Driver1 | 1 | 20 1 | Race1 | 2 | Driver2 | 2 | 15 1 | Race1 | 3 | Driver3 | 3 | 10 1 | Race1 | 4 | Driver4 | 4 | 5 1 | Race1 | 5 | SlowPoke | 20 | 0 2 | Race2 | 1 | Driver1 | 1 | 10 2 | Race2 | 2 | Driver2 | 2 | 8 2 | Race2 | 3 | Driver3 | 3 | 6 2 | Race2 | 4 | Driver4 | 4 | 3 2 | Race2 | 5 | SlowPoke | 40 | 0
我使用ISNULL(ps.PointsAwarded,0)
和LEFT OUTER JOIN
来确保驾驶员在未分配点值的位置上获得0
点。
如果需要,可以将其简化很多,但是它可能会限制查询的增长方式或导致重复数据的方式。同样,如果您的要求不同,则此结构可能会更改。
db <>提琴here
注意:您还可以轻松地向您的查询中添加“总运行点数”:
将RaceDate
添加到RaceDetails
。
将, SUM(ISNULL(ps.PointsAwarded,0)) OVER(PARTITION BY rrr.DriverID
ORDER BY rd.RaceDate ROWS UNBOUNDED PRECEDING) AS
PointsAwarded_RunningTotal
添加到SELECT
https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=e477dbd2e978f685da59d548d1fe3b15