Как обновить столбец "Баллы" победителей с помощью СУММ на сервере SQL - PullRequest
0 голосов
/ 13 июля 2020

У меня есть турнир, где в одном раунде могут быть несколько победителей и проигравших. Как мне обновить очки победителей до 10% от общего количества очков проигравших.

Вот пример:

ПРИМЕР 1

Энн, Бетти, Шарлотта и Брайан - все начните с 1000 очков. Они играют одну игру вист, причем выигрывают Энн и Бетти.

Победители (Энн и Бетти) должны иметь 1% очков проигравших.

Проигравшие (Шарлотта и Брайан) имеют в сумме 2000 очков.

Следовательно, 1% очков проигравших составляют 20 очков.

Это дает по 10 очков каждому из двух победителей (Энн и Бетти).

Результат после игры

Энн: 1010 очков Бетти: 1010 очков Шарлотта: 990 очков Брайан: 990 очков

ПРИМЕР 2

В другой игре Эрик, Фредерик, Гуннар и Хельге играть. Для удобства все они также начинаются с 1000 очков.

В этой игре Эрик получает возможность выиграть, а остальные трое проигрывают.

Таким образом, у Эрика должен быть 1% очков других игроков.

Фредерик, Гуннар и Хельге набрали в общей сложности 3000 очков.

1% очков проигравших, таким образом, составляет 30.

Эти 30 очков нужно добавить к общему количеству очков Эрика. очков, тогда как каждый из трех проигравших должен вычесть по 10 очков.

Результат после игры, таким образом,

Эрик 1030 очков Фредерик: 990 очков Гуннар: 990 очков Выходные: 990 очков

Я пробовал что-то подобное, но очки победителей обновляются только с 10% их собственных очков

BEGIN TRAN

UPDATE Players
SET Point = Point + 0.01 * (select distinct Point from Result where Winner = '0')
FROM Result
INNER JOIN Players ON Players.ID = Result.PlayerID
WHERE Winner = 1;

COMMIT TRAN;

Вот мои таблицы:

CREATE TABLE Players
(
    ID      INT IDENTITY (1,1) PRIMARY KEY, 
    Name    VARCHAR(50) NOT NULL,   
    Point   INT         NOT NULL
);

CREATE TABLE Round
(
    ID INT IDENTITY(1, 1) PRIMARY KEY,
    Player1 INT FOREIGN KEY REFERENCES Players(ID)  NOT NULL,
    Player2 INT FOREIGN KEY REFERENCES Players (ID) NOT NULL,
    Player3 INT FOREIGN KEY REFERENCES Players(ID)  NOT NULL,
    Player4 INT FOREIGN KEY REFERENCES Players(ID)  NOT NULL
);

CREATE TABLE Result
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    RoundID  INT FOREIGN KEY REFERENCES Round(ID)   NOT NULL,
    PlayerID INT FOREIGN KEY REFERENCES Players(ID) NOT NULL,
    Winner BIT NOT NULL
);
    
  
  INSERT INTO Players (Name, Point)
  VALUES 
  ('Morten', 1000),
  ('Jens', 1000),
  ('Mie', 1000),
  ('Sanne', 1000);

INSERT INTO Round (Player1, Player2, Player3, Player4)
VALUES 
  ('1', '2', '3', '4');

INSERT INTO Result (RoundID, PlayerID, Winner)
VALUES 
  ('1', '1', '1'),
  ('1', '2', '1'),
  ('1', '3', '0'),
  ('1', '4', '0'),
  ('2', '1', '1'),
  ('2', '2', '0'),
  ('2', '3', '0'),
  ('2', '4', '0');

1 Ответ

0 голосов
/ 13 июля 2020

Спасибо за дополнительную информацию о расчете. Вы сделали жизнь немного сложнее, чем это должно быть, с вашей структурой таблицы. Этот запрос требует нескольких шагов, чтобы сначала его разбить, но я думаю, что он делает то, что вам нужно:

WITH round_summary as
(
    SELECT 
        roundID
    ,   loss_points = sum(case when winner = 0 then point end)
    ,   count_winners = count(case when winner = 1 then playerID end)
    from
        Result
        join Players on Result.PlayerID = Players.ID
    group BY
        roundID
)

, round_unpvt as
(
    Select
        roundID = ID
    ,   playerID
    from
        [round]
        cross apply
        (   values
            ([Player1]) 
        ,   ([Player2]) 
        ,   ([Player3])
        ,   ([Player4])
        ) unpvt(playerID)
)

, points_calc as
(
    Select 
        round_unpvt.PlayerID
    ,   new_points = sum(0.1 * loss_points / count_winners)
    From
        round_unpvt
        join round_summary
            on round_unpvt.roundID = round_summary.roundID
        join result
            on result.roundID = round_unpvt.roundID
            and result.playerID = round_unpvt.playerID
    where
        winner = 1
    group by
        round_unpvt.PlayerID
)

UPDATE Players
SET [Point] = [Point] + new_points
FROM Players
INNER JOIN points_calc ON Players.ID = points_calc.PlayerID

Делает "круглую" таблицу более похожей на застежку-молнию (четыре строки, по одной для каждого игрока, за раунд, а не все в одной строке) упростит этот запрос.

...