如果我有这样的数据:
Id, Team1, Team2, Score1, Score2
--------------------------------
1, Aaa, Bbb, 10, 8
2, Aaa, Bbb, 6, 8
3, Aaa, Bbb, 6, 5
4, Bbb, Aaa, 9, 7
5, Aaa, Ccc, 12, 6
如何获得各个团队之间得分差异的列(运行汇总)? 例如:
Id, Team1, Team2, Score1, Score2 Abs(DIFF)
-------------------------------- ---------
1, Aaa, Bbb, 10, 8 2
2, Aaa, Bbb, 6, 8 0
3, Aaa, Bbb, 6, 5 1
4, Bbb, Aaa, 7, 9 3
5, Aaa, Ccc, 12, 6 6
请注意以上示例中的两件事:
是否可以在不使用游标或更新技巧的情况下获取此DIFF列? 查询必须在SQL Server 2008上运行。
我很少做DB工作,欢迎这么简单的解释。
更新其他说明:
因此,通过查看DIFF值,人们应该能够回答诸如“团队之间当前得分差异是什么?”这样的问题。
答案 0 :(得分:2)
使用您的第二个样本数据(第3行绑定在第一个样本中,第4行绑定分数开关侧):
declare @t table (Id int not null,Team1 char(3) not null,Team2 char(3) not null,
Score1 int not null,Score2 int not null)
insert into @t(Id, Team1, Team2, Score1, Score2) values
(1, 'Aaa', 'Bbb', 10, 8),
(2, 'Aaa', 'Bbb', 6, 8),
(3, 'Aaa', 'Bbb', 6, 5),
(4, 'Bbb', 'Aaa', 7, 9),
(5, 'Aaa', 'Ccc', 12, 6)
;With NormTeams as (
select Id,
CASE WHEN Team1 < Team2 THEN Team1 ELSE Team2 END as Team1,
CASE WHEN Team1 < Team2 THEN Team2 ELSE Team1 END as Team2,
CASE WHEN Team1 < Team2 THEN Score1 ELSE Score2 END as Score1,
CASE WHEN Team1 < Team2 THEN Score2 ELSE Score1 END as Score2,
(Score1 - Score2) * CASE WHEN Team1 < Team2 THEN 1 ELSE -1 END as ScoreDiff
from @t
), MatchingTeams as (
select *,ROW_NUMBER() OVER (PARTITION By Team1,Team2 ORDER BY ID) as rn
from NormTeams
)
select *,
(SELECT SUM(ScoreDiff) from MatchingTeams mt2 where
mt2.Team1 = mt1.Team1 and mt2.Team2 = mt1.Team2 and
mt2.rn <= mt1.rn) as RunningDiff
from MatchingTeams mt1
遗憾的是,在您使用2012 windowed aggregates之前,没有什么可以使它更整洁。
结果:
Id Team1 Team2 Score1 Score2 ScoreDiff rn RunningDiff
----------- ----- ----- ----------- ----------- ----------- -------------------- -----------
1 Aaa Bbb 10 8 2 1 2
2 Aaa Bbb 6 8 -2 2 0
3 Aaa Bbb 6 5 1 3 1
4 Aaa Bbb 9 7 2 4 3
5 Aaa Ccc 12 6 6 1 6
你会注意到我做的第一件事就是显而易见的 - 如有必要,可以转换团队和分数,以便查询的其余部分可以假设他们做以一致的顺序出现
答案 1 :(得分:0)
你可以试试这个:
编辑:修复了team1&amp; team2交换。
; WITH CTE AS (
SELECT
Id
, Team1
, Team2
, Score1
, Score2
, ROW_NUMBER() OVER (PARTITION BY X.Teams ORDER BY ???) AS Row
FROM MyTable
CROSS APPLY (
SELECT
Team1 + '_' + Team2 -- Use something else than '_' if this caracter can exist in team's names
WHERE Team1 < Team2
UNION ALL
SELECT
Team2 + '_' + Team1
WHERE Team1 > Team2
) AS X(Teams)
)
SELECT
T1.Id
, T1.Team1
, T1.Team2
, T1.Score1
, T1.Score2
, ABS((T1.Score1 + ISNULL(T2.Score1, 0)) - (T1.Score2 + ISNULL(T2.Score2, 0))) AS Abs(DIFF)
FROM CTE AS T1
OUTER APPLY (
SELECT
SUM(T2.Score1) AS Score1
, SUM(T2.Score2) AS Score2
FROM CTE AS T2
WHERE T2.Teams = T1.Teams
AND T2.Row < T1.Row
) AS T2
答案 2 :(得分:0)
试试这个:
;WITH CTE as
(
select id,Team1,Team2,Score1,Score2,0 as RS1,0 as RS2,ABS(Score1-Score2) as DIFF from Table1 where id=1
UNION ALL
select t1.id,t1.Team1,t1.Team2,t1.Score1,t1.Score2,c.score1+t1.Score1,c.score2+t1.Score2,ABS((c.score1+t1.Score1)-(c.score2+t1.Score2)) as DIFF
from Table1 t1 inner join CTE c
on c.id+1=t1.id and ((t1.Team1 = c.team1 and t1.Team2 = c.Team2) or (t1.Team2 = c.team1 and t1.Team1 = c.Team2))
)
,CTE1 As
(
select * from CTE
union
select id,Team1,Team2,Score1,Score2,0,0,ABS(Score1-Score2) as DIFF from Table1 where id not in(select id from CTE)
)
select id,Team1,Team2,Score1,Score2,DIFF from CTE1