我有一个25场比赛结果的数据库。但是只有每个人最好的十分数。 任何人都可以告诉我如何只计算每个人的前十个分数,并显示该总和中使用的最低分数(他们的第十好)。 该数据库具有PlayerName,TournamentID,Points 例如
- TounamentID PlayerName Points
- 1 Jo 100
- 1 Tel 50
- 1 Kevin 75
- 2 Jo 100
- 2 Tel 50
- 2 Kevin 75
- 3 Jo 100
- 3 Tel 50
- 3 Kevin 75
- 4 Jo 100
- 4 Tel 50
- 4 Kevin 75
- 5 Jo 100
- 5 Tel 50
- 5 Kevin 75 etc
非常感谢提前
编辑 1
目前我有这种工作,虽然它不能很好地处理重复的分数,如果有重复,实际上最终可以加上前11名;
SELECT X.PlayerName, Sum(X.Points) AS SumOfPoints, Min(X.Points) AS Target
FROM SoP11PreBats AS X
WHERE (((10)>(SELECT count(*)
FROM SoP11PreBats
WHERE PlayerName = X.PlayerName
AND Points > X.Points )))
GROUP BY X.PlayerName
ORDER BY Sum(X.Points) DESC;
答案 0 :(得分:1)
这样的事情一次对一个玩家有效:
SELECT SUM(n), MIN(n) FROM
(SELECT points AS n
FROM table
WHERE PlayerName = ?
ORDER BY n DESC
LIMIT 10
)
我不确定如何扩展它以为每个播放器生成一个表。
答案 1 :(得分:1)
SELECT test.playername, sum(top10.score), MIN(top10.score)
FROM test
LEFT JOIN (SELECT playername, score FROM test ORDER BY score DESC LIMIT 10) top10
ON top10.playername = test.playername
GROUP BY test.playername
编辑:使用子选择结果显示上述方法,并且连接不会成功。因为您在子选择中限制结果,所以不会导致一组最多10个记录PER playername。
接下来的方法是做一些像
SELECT pk, name, score from test where
pk IN (SELECT pk FROM test t2 WHERE t2.name = name ORDER BY score DESC LIMIT 10)
这可以创建要加入的正确记录集。但是IN子句(尚未)内部不支持LIMIT。所以这不会编译。
EIDT2:我能想到的最终方法是这样的:
select distinct test.name
, (SELECT sum(t2.score) FROM (select t3.score FROM test t3 WHERE t3.name = test.name ORDER BY score desc LIMIT 10) t2)
, (SELECT min(t2.score) FROM (select t3.score FROM test t3 WHERE t3.name = test.name ORDER BY score desc LIMIT 10) t2)
FROM test
这个也不会编译,因为最里面的test.name在哪里无法正确解析。
我不认为你想要做的事情目前可以在mysql的1个单一查询中完成,但我很好奇是否有人可以证明我错了。
答案 2 :(得分:1)
好的,我得到了它的工作,但它是关于我能想到的最讨厌的sql hack,我不确定你是否应该考虑将它投入到这样的生产中。它也只能在mysql上运行:
select PlayerName, sum(Points), min(Points) from
(select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 1,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 2,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 3,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 4,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 5,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 6,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 7,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 8,1) as Points FROM test
UNION ALL
select distinct SoP11PreBats.PlayerName, (SELECT t2.Points FROM test t2 WHERE t2.PlayerName = SoP11PreBats.PlayerName ORDER BY Points desc LIMIT 9,1) as Points FROM test
) top10
group by name
答案 3 :(得分:0)
我觉得这不起作用:
SELECT *
FROM
( SELECT pd.PlayerName
, ( SELECT SUM(t10.Points)
FROM
( SELECT t10.Points
FROM SoP11PreBats AS t10
WHERE t10.PlayerName = pd.PlayerName
ORDER BY t10.Points DESC
LIMIT 10
) AS x
) AS Sum10
, ( SELECT t10.Points
FROM SoP11PreBats AS t10
WHERE t10.PlayerName = pd.PlayerName
ORDER BY t10.Points DESC
LIMIT 1 OFFSET 9
) AS TenthBest
FROM
( SELECT DISTINCT PlayerName
FROM SoP11PreBats
) AS pd
) AS y
ORDER BY Sum10 DESC
但这会:
SELECT pb.PlayerName AS PlayerName
, COALESCE(SUM(p.Points),0) + pb.TenthBest*(10-COUNT(p.Points))
AS SumOfPoints
, pb.TenthBest AS Target
FROM
( SELECT pd.PlayerName
, ( SELECT t10.Points
FROM SoP11PreBats AS t10
WHERE t10.PlayerName = pd.PlayerName
ORDER BY t10.Points DESC
LIMIT 1 OFFSET 9
) AS TenthBest
FROM
( SELECT DISTINCT PlayerName
FROM SoP11PreBats
) AS pd
) AS pb
LEFT JOIN SoP11PreBats AS p
ON p.PlayerName = pb.PlayerName
AND p.Points > pb.TenthBest
GROUP BY pb.PlayerName
ORDER BY SumOfPoints DESC
答案 4 :(得分:0)
这有效(见下面的测试输出):
set @count:=0, @player:='';
SELECT
PlayerName,
SUM(Points) as sum_top_10,
MIN(Points) as min_top_10
FROM (SELECT PlayerName, Points
FROM (SELECT
Points,
@count := if (@player != PlayerName, 0, @count + 1) as count,
@player := PlayerName as PlayerName
FROM (SELECT PlayerName, Points FROM SoP11PreBATS order by 1, 2 desc) x) y
where count < 10) z
group by 1;
以下是测试,使用OP的数据,以及'Jo'的额外行,以产生超过10行:
create table SoP11PreBATS (TounamentID int, PlayerName text, Points int);
delete from SoP11PreBATS;
insert into SoP11PreBATS values
(1, 'Jo', 100), (1, 'Tel', 50), (1, 'Kevin', 75), (2, 'Jo', 100), (2, 'Tel', 50),
(2, 'Kevin', 75), (3, 'Jo', 100), (3, 'Tel', 50), (3, 'Kevin', 75), (4, 'Jo', 100),
(4, 'Tel', 50), (4, 'Kevin', 75), (5, 'Jo', 100), (5, 'Tel', 50), (5, 'Kevin', 75),
(5, 'Jo', 50), (6, 'Jo', 75), (7, 'Jo', 100), (8, 'Jo', 50), (9, 'Jo', 75),
(10, 'Jo', 50), (11, 'Jo', 75), (12, 'Jo', 100);
select * from SoP11PreBATS where playername = 'Jo' order by points desc;
+-------------+------------+--------+
| TounamentID | PlayerName | Points |
+-------------+------------+--------+
| 1 | Jo | 100 |
| 2 | Jo | 100 |
| 3 | Jo | 100 |
| 4 | Jo | 100 |
| 5 | Jo | 100 |
| 7 | Jo | 100 |
| 12 | Jo | 100 |
| 6 | Jo | 75 |
| 9 | Jo | 75 |
| 11 | Jo | 75 |
| 5 | Jo | 50 |
| 8 | Jo | 50 |
| 10 | Jo | 50 |
+-------------+------------+--------+
-- Inspection shows Jo should have 925 as sum and 75 as min
-- Ran query above and got:
+------------+------------+------------+
| PlayerName | sum_top_10 | min_top_10 |
+------------+------------+------------+
| Jo | 925 | 75 |
| Kevin | 375 | 75 |
| Tel | 250 | 50 |
+------------+------------+------------+
-- Test output correct
答案 5 :(得分:0)
我认为这是有效的,它只使用一个派生表:
SELECT @row := 0, @pp := NULL, @min := 0;
SELECT Player,
SUM(Points) AS Points,
MIN(Points) AS MinPoints
FROM (
SELECT Player,
Points,
@row := IF(
IFNULL(@pp, '') <> Player AND NOT (@pp := Player),
1,
@row + 1
) AS Row
FROM SoP11PreBats
ORDER BY Player, Points DESC
) tmp
WHERE tmp.Row <= 10
GROUP BY Player;
测试数据:
CREATE TABLE `SoP11PreBats` (
`TournamentID` int(11) NOT NULL,
`Player` varchar(255) NOT NULL,
`Points` int(11) NOT NULL
);
INSERT INTO SoP11PreBats (TournamentID, Player, Points) VALUES
(15, 'Jo', 10),
(14, 'Jo', 20),
(13, 'Jo', 30),
(12, 'Jo', 40),
(11, 'Jo', 50),
(10, 'Jo', 60),
( 9, 'Jo', 70),
( 8, 'Jo', 80),
( 7, 'Jo', 90),
( 6, 'Jo', 100),
( 5, 'Jo', 110),
( 4, 'Jo', 120),
( 3, 'Jo', 130),
( 2, 'Jo', 140),
( 1, 'Jo', 150),
( 1, 'Tel', 15),
( 2, 'Tel', 25),
( 3, 'Tel', 35),
( 4, 'Tel', 45),
( 5, 'Tel', 55),
( 6, 'Tel', 65),
( 7, 'Tel', 75),
( 8, 'Tel', 85),
( 9, 'Tel', 95),
(10, 'Tel', 105),
(11, 'Tel', 115),
(12, 'Tel', 125),
(13, 'Tel', 135),
(14, 'Tel', 145),
(15, 'Tel', 155),
( 1, 'Kevin', 10),
( 2, 'Kevin', 20),
( 3, 'Kevin', 30),
( 4, 'Kevin', 40),
( 5, 'Kevin', 50),
( 6, 'Kevin', 60),
( 7, 'Kevin', 70),
( 8, 'Kevin', 80),
( 9, 'Kevin', 90),
(10, 'Kevin', 100),
(11, 'Kevin', 110),
(12, 'Kevin', 120),
(13, 'Kevin', 130),
(14, 'Kevin', 140),
(15, 'Kevin', 150);
结果:
+--------+--------+-----------+
| Player | Points | MinPoints |
+--------+--------+-----------+
| Jo | 1050 | 60 |
| Kevin | 1050 | 60 |
| Tel | 1100 | 65 |
+--------+--------+-----------+