如何在MS SQL中将guid字段从1行交换到另一行? [英] How do I swap guid fields from 1 row to another in MS SQL ?

查看:66
本文介绍了如何在MS SQL中将guid字段从1行交换到另一行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我对SQL很新,所以我可能会离开这里,但这就是我想做的事情。我有tblFixtures,其中包含Guid的玩家,这些玩家在Pool Knockout中被吸引到对方玩耍。 tblFixtures有uniqueidentifier列player1和player2。我已经添加了'Byes',因为像这样的淘汰赛所需的总玩家数是8 ..所以例如,如果在tblFixtures中只有6名玩家,它会添加2个空白玩家并且Guid为'00000000-0000-0000-0000- 000000000000' 。因此,2名玩家将获得下一轮(A'Bee')的免费通行证,但我需要重新安排桌子,以防BYE最终对抗这样的BYE。





玩家1玩家2

{72462373-6B64-4427-9F9F-9A872261A333} v {9C90B324-78CA-4C7B-BC79-15537F3935B2}

{00000000-0000-0000-0000-000000000000} v {00000000-0000-0000-0000-000000000000}

{3E828BB1-AEC2-4543-BD26-E12AD886D2E8} v {72462373-6B64-4427-9F9F-9A872261ABC2}

{4F9C3964-2672-4413-8A01-2ED09CA7A711} v {AFEB20EB-5CCB-4302-A999-CC772F8ABACE}

我需要把空Guid的ANYWHERE对抗这样的球员Guid ..





球员1球员2

{72462373-6B64-4427-9F9F-9A872261A333} v {9C90B324-78CA-4C7B-BC79-15537F3935B2}

{3E828BB1-AEC2-4543-BD26-E12AD886D2E8} v {00000000 0000-0000-0000-000000000000}

{00000000-0000-00 00-0000-000000000000} v {72462373-6B64-4427-9F9F-9A872261ABC2}

{4F9C3964-2672-4413-8A01-2ED09CA7A711} v {AFEB20EB-5CCB-4302-A999-CC772F8ABACE}



下面的代码需要OVER命令和我认为的一些调整,但这是我能得到的。我要做的是检查有多少玩家(包括BYES),所以在这种情况下有8个,并存储在@matches中。现在我希望它一次检查一行,使用一个等于@matches中存储量的循环。这个检查查找空白0的Guid播放空白0的Guid。如果找到它,那么它将替换此行中的Player1与下一个没有空白的玩家1 Guid它找到并将其归零。



我只是不知道了解OVER还是不确定其余的代码是否真的有效或者有没有人知道更简单的方法呢?



任何帮助表示感谢。这是我到目前为止所拥有的......



DECLARE @matchess int

SELECT @matches =来自tblFixtures的COUNT(accountID)*



DECLARE @cnt INT = 0



我的尝试:



Ok, I'm fairly new to SQL so I'm probably way off here but here's what I want to do. I have tblFixtures which holds Guid's of players who have been drawn to play each other in a Pool Knockout. tblFixtures has uniqueidentifier columns player1 and player2. I have already added 'Byes' because total players needed for a knockout like this is 8.. so for example, if a there's only 6 players in tblFixtures, it adds 2 blank players with Guid of '00000000-0000-0000-0000-000000000000'. Therefore 2 players will get a 'Free pass to the next round (A 'Bye') but I need to re-arrange the table in case a BYE ends up drawn against a BYE like this.


Player 1 Player 2
{72462373-6B64-4427-9F9F-9A872261A333} v {9C90B324-78CA-4C7B-BC79-15537F3935B2}
{00000000-0000-0000-0000-000000000000} v {00000000-0000-0000-0000-000000000000}
{3E828BB1-AEC2-4543-BD26-E12AD886D2E8} v {72462373-6B64-4427-9F9F-9A872261ABC2}
{4F9C3964-2672-4413-8A01-2ED09CA7A711} v {AFEB20EB-5CCB-4302-A999-CC772F8ABACE}
I need it to put the empty Guid's ANYWHERE against a players Guid like this..


Player 1 Player 2
{72462373-6B64-4427-9F9F-9A872261A333} v {9C90B324-78CA-4C7B-BC79-15537F3935B2}
{3E828BB1-AEC2-4543-BD26-E12AD886D2E8} v {00000000-0000-0000-0000-000000000000}
{00000000-0000-0000-0000-000000000000} v {72462373-6B64-4427-9F9F-9A872261ABC2}
{4F9C3964-2672-4413-8A01-2ED09CA7A711} v {AFEB20EB-5CCB-4302-A999-CC772F8ABACE}

The code below requires OVER command and a few tweaks I think, but this is as far as I could get. What I am trying to do is check how many players (including BYES) there are, so in this case there's 8 and that's stored in @matches. Now I want it to check a row at a time, using a loop equal to the amount stored in @matches.. This check looks for a blank 0's Guid playing a blank 0's Guid. If it is found then it will replace Player1 in this row with the next none blank player1 Guid it finds and zero that one out instead.

I just don't know understand OVER yet and unsure the rest of the code will actually work OR does anyone know an easier way to do this?

Any help appreciated. Here's what I have so far..

DECLARE @matchess int
SELECT @matches = COUNT(accountID) from tblFixtures)*

DECLARE @cnt INT = 0

What I have tried:

SELECT player1, ROW_NUMBER() OVER (ORDER BY player1) AS RowNumber
FROM   tblFixtures


DECLARE @Players int
SELECT @Players = COUNT(accountID) from tblEntrants WHERE paid='y'

DECLARE @cnt INT = 0

WHILE @cnt < @Players
    BEGIN

    If (SELECT Player1 WHERE ROW_NUMBER()  OVER (ORDER BY Player1) FROM tblFixtures)=@cnt = '00000000-0000-0000-0000-000000000000' AND SELECT(player1 WHERE ROW_NUMBER()  OVER (ORDER BY Player1 FROM tblFixtures)= @cnt) ='00000000-0000-0000-0000-000000000000' THEN
        BEGIN
            UPDATE tblFixtures SET Player1 = SELECT(TOP(1) player1  WHERE player1 <> '00000000-0000-0000-0000-000000000000' AND ROW_NUMBER()  OVER (ORDER BY Player1) FROM tblFixtures>@cnt) WHERE ROW_NUMBERr()  OVER (ORDER BY Player1) FROM tblFixtures=@cnt
            UPDATE tblFixtures SET Player1 = '0000-0000-0000-0000' WHERE SELECT(Top(1) player1) <> '00000000-0000-0000-0000-000000000000' AND ROW_NUMBER() FROM tblFixtures>@cnt 
        END
    SET @cnt = @cnt + 1
END

推荐答案

这样的事情应该有效:

Something like this should work:
-- Count the number of real players:
DECLARE @EntrantCount int;

SELECT
    @EntrantCount = Count(1)
FROM
    tblEntrants
WHERE
    paid = 'y'
;


-- Find the next highest power of 2 - the total number of players required:
DECLARE @PlayerCount int = POWER(2, CEILING(LOG(@EntrantCount, 2)));


-- Generate a random order for all entrants and byes:
DECLARE @AllPlayers TABLE 
(
    RN int NOT NULL Primary Key, 
    ID uniqueidentifier NULL
);

WITH ctePlayers As
(
    SELECT
        ID
    FROM
        tblEntrants
    WHERE
        paid = 'y'

    UNION ALL

    SELECT TOP (@PlayerCount - @EntrantCount)
        Null
    FROM
        sys.objects
),
cteOrderedPlayers As
(
    SELECT
        ROW_NUMBER() OVER (ORDER BY NewID()) As RN,
        ID
    FROM
        ctePlayers
)
INSERT INTO @AllPlayers
(
    RN,
    ID
)
SELECT
    RN,
    ID
FROM
    cteOrderedPlayers
;


-- Build the random fixtures:
DECLARE @Fixtures TABLE 
(
    RN int NOT NULL IDENTITY(1, 1) Primary Key, 
    Player1 uniqueidentifier NULL, 
    Player2 uniqueidentifier NULL
);

WITH cteFixtures As
(
    SELECT
        P1.ID As Player1,
        P2.ID As Player2
    FROM
        @AllPlayers As P1
        LEFT JOIN @AllPlayers As P2
        ON P2.RN = P1.RN + 1
    WHERE
        -- Only take the odd-numbered rows for player 1:
        (P1.RN & 1) = 1
)
INSERT INTO @Fixtures
(
    Player1,
    Player2
)
SELECT
    Player1,
    Player2
FROM
    cteFixtures
;


-- Resolve "bye-bye" rows:
WHILE Exists(SELECT 1 FROM @Fixtures WHERE Player1 Is Null And Player2 Is Null)
BEGIN
    DECLARE @R1 int, @R2 int, @ID uniqueidentifier;

    -- Find the first row without a player:
    SELECT TOP 1 
        @R1 = RN 
    FROM 
        @Fixtures 
    WHERE 
        Player1 Is Null 
    And 
        Player2 Is Null
    ;

    -- Find the first row with a player on both sides:
    SELECT TOP 1
        @R2 = RN,
        @ID = Player1
    FROM
        @Fixtures
    WHERE
        Player1 Is Not Null
    And
        Player2 Is Not Null
    ;

    IF @@ROWCOUNT = 0
    BEGIN
        -- Just in case, to avoid an infinite loop, although I'm 99.9% sure this will never happen:
        RAISERROR('No way to resolve - should never happen.', 16, 1);
    END;

    -- Swap player 1:
    UPDATE
        @Fixtures
    SET
        Player1 = CASE RN
            WHEN @R1 THEN @ID
            ELSE Null
        END
    WHERE
        RN In (@R1, @R2)
    ;
END;


-- Finished:
INSERT INTO tblFixtures
(
    Player1,
    Player2
)
SELECT
    IsNull(Player1, '00000000-0000-0000-0000-000000000000'),
    IsNull(Player2, '00000000-0000-0000-0000-000000000000')
FROM
    @Fixtures
;


这篇关于如何在MS SQL中将guid字段从1行交换到另一行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆