秘密圣诞老人抽奖的 SQL 过程允许自我赠送礼物

问题描述 投票:0回答:1

我开发了一个 SQL 存储过程,旨在自动在一群人中抽奖神秘圣诞老人。该程序应该为每个人随机分配其他人礼物,而不是任何人自己赠送礼物。然而,我遇到了一个问题,个人最终可能被分配给自己送礼物,这在秘密圣诞老人设置中是不希望的。

这是我正在使用的 SQL 代码:

CREATE DATABASE IF NOT EXISTS AMIGOINVISIBLE;

USE AMIGOINVISIBLE;

CREATE TABLE IF NOT EXISTS CaseA(
     id INT PRIMARY KEY AUTO_INCREMENT,
     people VARCHAR(50),
     peopleToGift VARCHAR(50)  );

INSERT INTO CaseA (people, peopleToGift) 
VALUES  ('a.tomas', NULL), ('g.rubio', NULL), ('a.pulido', NULL), ('m.fabrega.1', NULL), ('d.lazaro', NULL), ('c.albinya', NULL), ('b.gomez', NULL),`
 `('j.espinoza', NULL), ('j.aguilera', NULL), ('j.da.silva.1', NULL), ('a.chamorro', NULL);

DELIMITER //

CREATE OR REPLACE PROCEDURE randomizePeople()
 BEGIN
     DECLARE times INT;
     DECLARE Counter INT;
     DECLARE random1 INT;
     DECLARE random2 INT;
     DECLARE aux INT;
     DECLARE position INT;
     DECLARE peopleToGift VARCHAR(50);

     SELECT COUNT(*) INTO times FROM CaseA;
     DROP TABLE IF EXISTS order;
     CREATE TEMPORARY TABLE IF NOT EXISTS order (
         id INT PRIMARY KEY AUTO_INCREMENT,
         Number INT
     );
     SET Counter = 1;
     WHILE Counter <= times DO
         INSERT INTO order (Number) VALUES (Counter);
         SET Counter = Counter + 1;
     END WHILE;

     SET Counter = 1;

     WHILE Counter <= times DO
         SET random1 = FLOOR(RAND() * times) + 1;
         SET random2 = FLOOR(RAND() * times) + 1;

         SELECT Number INTO aux FROM order WHERE id = random1;
         UPDATE order SET Number = (SELECT Number FROM order WHERE id = random2) WHERE id = random1;
         UPDATE order SET Number = aux WHERE id = random2;

         SET Counter = Counter + 1;
     END WHILE;

     SET Counter = 1;

     WHILE Counter <= times DO
         SELECT Number INTO position FROM order WHERE id = Counter;
         SELECT people INTO peopleToGift FROM CaseA WHERE id = position;
         SELECT position, peopleToGift;

         UPDATE CaseA SET peopleToGift = peopleToGift WHERE id = Counter;
         SET Counter = Counter + 1;
     END WHILE;
END
//  DELIMITER;
DELIMITER ;
sql mysql mariadb
1个回答
0
投票

您可以通过首先为每个人随机分配一个行号来做到这一点:

SELECT id, people, ROW_NUMBER() OVER(ORDER BY RAND()) AS RowNumber, COUNT(*) OVER() AS TotalCount
FROM CaseA

然后您可以将每个人与下一个人配对,例如RowNumber 1 和 RowNumber2 等,这确保没有人可以与自己配对。唯一需要注意的是,您需要将最后一行与第一行配对,因此您需要对连接使用模数检查来执行此操作。

作为选择,它看起来像这样:

 WITH RandomOrder AS
 (  SELECT id, 
           people, 
           ROW_NUMBER() OVER(ORDER BY RAND()) AS RowNumber, 
           COUNT(*) OVER() AS TotalCount
    FROM CaseA
 )
SELECT r1.id, r1.people, r1.RowNumber, r2.people AS peopleToGift
FROM RandomOrder AS r1
 INNER JOIN RandomOrder AS r2
    ON r2.RowNumber = (r1.RowNumber % r1.TotalCount) + 1
ORDER BY r1.id;

或者要更新基表本身,您可以将其转换为更新,如下所示:

 WITH RandomOrder AS
 (  SELECT id, 
           people, 
           ROW_NUMBER() OVER(ORDER BY RAND()) AS RowNumber, 
           COUNT(*) OVER() AS TotalCount
    FROM CaseA
 )
UPDATE CaseA AS c
INNER JOIN RandomOrder AS r1
  ON r1.id = c.id
 INNER JOIN RandomOrder AS r2
    ON r2.RowNumber = (r1.RowNumber % r1.TotalCount) + 1
SET c.PeopleToGift = r2.people;

SQLFiddle 示例

© www.soinside.com 2019 - 2024. All rights reserved.