【问题标题】:SQL QUERY: How to assign random different value of column in a table, to differents row in another table?SQL QUERY:如何将表中列的随机不同值分配给另一个表中的不同行?
【发布时间】:2016-07-02 18:36:51
【问题描述】:

我正在开发一个桌面应用程序,该应用程序的工作原理类似于 Risiko! 的游戏,基于一些数据库程序。

我需要为每个玩家分配一组彼此不相等的行,分配给其他玩家。

我尝试过这样的事情,但没有用:

 `create or replace PROCEDURE  "giveterritory"
    (idpartita NUMBER,nr_partecipanti number )
   is

 begin

 DECLARE

 CURSOR cur_file IS

SELECT *
FROM Player
WHERE idgame = Player.idgame ;

var_cur cur_file%ROWTYPE;

cont number ;
nr_territories_gioc_prec number ;
G1_Terr int ;  
G2_Terr int ;  
G3_Terr int ;
G1_ID number;
G2_ID number;
G3_ID number;
begin

cont:=0 ;

for var_cur in cur_file 

loop

cont := cont + 1 ;  

    update territory
    set    Player_owner = var_cur.id_Player
    where ROWNUM = MOD( MOD ( number_RANDOM(),42 ) ,ROWNUM );
 G1_Terr := var_cur.number_territories_tot ;   -- mi salvo i territories del primo Player
 G1_ID := var_cur.id_Player ;
 end if ;
   if (cont=2 ) then 


    update territory
    set    Player_owner = var_cur.id_Player
    where ROWNUM = MOD( MOD ( number_RANDOM(),42 -G1_Terr ) , ROWNUM ) and id_territory NOT IN ( select Player_owner from territory where ;

    G2_Terr := var_cur.number_territories_tot  ;    
    end if ;
 if (cont=3 ) then 


    update territory
    set    Player_owner = var_cur.id_Player
    where ROWNUM <= 42 - G1_Terr - G2_Terr;
    --where ROWNUM <= 42 - var_cur.number_territories_tot * 2 ;
 G3_Terr := var_cur.number_territories_tot  ;   
 end if ;
 end loop;
 end;

end;`

number_随机码:

        create or replace FUNCTION  "NUMBER_RANDOM"
      return NUMBER
      is
      numbrndm int;
      begin

         select dbms_random.value(1,99999999) into numbrndm
        from dual;
   return numbrndm;
   end;

【问题讨论】:

  • 您的问题是什么?样本数据和期望的结果会有所帮助。
  • 有很多方法可以随机化事物,但发布您的结构和一些示例数据会有所帮助。那么另一个问题是你真的想要随机的还是更多的循环来平衡你的领土?
  • 平衡随机
  • 不要将 SOLVED 放在标题中。接受解决您问题的答案。如果您自己解决了问题,请将解决方案添加为答案并接受。

标签: sql oracle stored-procedures plsql


【解决方案1】:

如果我理解正确,您是在尝试为每个玩家随机分配一组区域?

如果是这样,请按随机顺序对区域进行排序,然后将它们分配给循环赛玩家。这是应该这样做的MERGE 声明。对于任何轻微的语法错误,我深表歉意:我现在不在 Oracle 数据库前。

MERGE INTO territory t
USING (
WITH players AS ( SELECT rownum player#, id_player
                  FROM   player
                  WHERE  idgame=:idgame ),
players_count AS ( SELECT count(*) players_count FROM players )
-- Get the id_player for each assignment
SELECT assignedt.id_territory, p.id_player
FROM
(
  -- Assign the randomly-ordered territories to players in round-robin format
  SELECT randt.id_territory, 
     mod(rownum, pc.players_count)+1 player#
  FROM (
    -- Query the territories in a random order
    SELECT t.id_territory
    FROM   territory t
    ORDER BY dbms_random.random ) randt, players_count pc
  -- Optional:
  -- ... add a where clause to limit rownum <= some number to make 
  -- ... sure each player receives an even number of territories. 
  -- ... You'd need the count of territories to do that.
  ) assignedt inner join players p on p.player# = assignedt.player#
) u
ON ( u.id_territory = t.id_territory )
WHEN MATCHED THEN UPDATE SET t.id_player = u.id_player;

【讨论】:

    【解决方案2】:

    我会在每行的 SQL 选择中放置一个随机数列。然后您可以直接在 SQL 中按随机数对您的记录集进行排序。

    对玩家和地区列表都这样做。

    此示例适用于任意数量的地区和玩家。如果领土分配不均,则随机获得一个额外领土的玩家。

    我们将按随机顺序遍历地区列表一次。我们将逐步遍历播放器列表,直到到达末尾,然后再次重新加载播放器列表。这会根据需要发生多次。

    可能需要针对语法或逻辑解决此问题。我没有 Oracle 实例来测试它。

    CREATE OR REPLACE PROCEDURE giveterritory (pID_GAME PLS_INTEGER) IS
        CURSOR c_player IS
            SELECT id_player, dbms_random.value() rnd
            FROM players
            WHERE id_game = pID_GAME
            ORDER BY 2 desc;
        --
        CURSOR c_territory IS
            SELECT id_territory, dbms_random.value() rnd
            FROM territories
            WHERE id_game = pID_GAME
            FOR UPDATE of id_player
            ORDER BY 2 desc;
        --
        l_player_row  c_player%ROWTYPE;
        l_territory_row  c_territory%ROWTYPE;
    BEGIN
        OPEN c_player;
        FETCH c_player into l_player_row;
        --
        FOR r in c_territory
        LOOP
            UPDATE territories
            SET id_player = l_player_row.id_player
            WHERE CURRENT OF c_territory;
            --
            FETCH c_player INTO l_player_row;
            IF c_player%NOTFOUND THEN
                CLOSE c_player;
                OPEN c_player;
                FETCH c_player INTO l_player_row;
            END IF;
        END LOOP;
    END;
    

    【讨论】:

    • 它不起作用,它将每个区域分配给最后一个玩家,以及不属于当前游戏的区域
    猜你喜欢
    • 1970-01-01
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    相关资源
    最近更新 更多