具有特殊条件的电子邮件地址的随机分配

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

给定一系列电子邮件地址,我需要将它们随机配对,条件是如果A要给B送礼物,那么B必须给A送礼物。如果电子邮件地址的数量是奇数,则后三个必须彼此配对(A 与 B、B 与 C、C 与 A)。我使用以下代码在 MySQL 中实现此功能:

CREATE TABLE IF NOT EXISTS CasoB(
    id INT PRIMARY KEY AUTO_INCREMENT,
    persons VARCHAR(50),
    personsToGive VARCHAR(50) 
);

INSERT INTO CasoB (persons, personsToGive) 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 GenerateRandomOrderB()
BEGIN
    DECLARE lineCount INT;

    -- Drop the temporary table if it exists
    DROP TEMPORARY TABLE IF EXISTS RandomOrderB;

    -- Create the temporary table
    CREATE TEMPORARY TABLE IF NOT EXISTS RandomOrderB (
        id INT PRIMARY KEY,
        persons VARCHAR(50),
        RowNumber INT,
        TotalCount INT
    );

    -- Get the number of lines in CasoB
    SELECT COUNT(*) INTO lineCount FROM CasoB;

    -- Insert data into the temporary table and get the total count
    INSERT INTO RandomOrderB (id, persons, RowNumber, TotalCount)
    SELECT  id, 
            persons,
            ROW_NUMBER() OVER(ORDER BY RAND()) AS RowNumber,
            lineCount AS TotalCount
    FROM    CasoB;

    IF lineCount % 2 = 0 THEN
        -- Even number of records
        -- Pair the persons
        UPDATE CasoB
        SET personsToGive = (
            SELECT r2.persons
            FROM RandomOrderB AS r1
            INNER JOIN RandomOrderB AS r2
            ON r2.RowNumber = r1.RowNumber + (lineCount / 2)
            WHERE r1.id = CasoB.id
        );
    ELSE
        -- Odd number of records
        -- Pair all persons except the last three
        UPDATE CasoB
        SET personsToGive = (
            SELECT r2.persons
            FROM RandomOrderB AS r1
            INNER JOIN RandomOrderB AS r2
            ON r2.RowNumber = r1.RowNumber + (lineCount / 2)
            WHERE r1.id = CasoB.id
        );

        -- Pair the last three persons among themselves
        UPDATE CasoB
        SET personsToGive = persons
        WHERE id IN (
            SELECT id
            FROM (
                SELECT id
                FROM RandomOrderB
                ORDER BY RowNumber DESC
                LIMIT 3
            ) AS lastThree
        );
    END IF;
    
    -- Drop the temporary table when finished
    DROP TEMPORARY TABLE IF EXISTS RandomOrderB;
END //

DELIMITER ;

我的问题,我认为代码是正确的,至少随机化偶数的部分是这样的

DROP TABLE IF EXISTS RandomOrder;

CREATE TEMPORARY TABLE IF NOT EXISTS RandomOrder (
    id INT PRIMARY KEY,
    people VARCHAR(50),
    RowNumber INT,
    TotalCount INT
);

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

UPDATE CaseA
SET peopleForGift = (
    SELECT r2.people
    FROM RandomOrder AS r1
    INNER JOIN RandomOrder AS r2
    ON r2.RowNumber = (r1.RowNumber % r1.TotalCount) + 1
    WHERE r1.id = CaseA.id
);

但是当涉及到将其随机化为奇数人时,首先对除最后3人之外的所有人进行随机化,然后仅对这3人进行随机化但是当涉及到将其随机化到奇数人时,进行随机化首先是除了最后 3 个人之外的所有人,然后仅随机化这 3 个人

sql mysql mariadb
1个回答
0
投票
WITH
cte1 (id, persons, personsToGive, rn) AS (
  SELECT id, persons, personsToGive, 
         ROW_NUMBER() OVER (ORDER BY RAND())
  FROM CasoB
  ),
cte2 (id, persons, personsToGive, rn, rnx) AS (
  SELECT id, persons, personsToGive, rn,
         CASE WHEN 0 = (SELECT COUNT(*) MOD 2 FROM CasoB)
              THEN ((rn + 1) DIV 2) * 4 - 1 - rn
              ELSE CASE WHEN rn > 3 
                        THEN (rn DIV 2) * 4 + 1 - rn
                        ELSE (rn MOD 3) + 1
                        END
              END
  FROM cte1                              
  )
UPDATE CasoB
  JOIN cte2 cte21 ON CasoB.id = cte21.id
  JOIN cte2 cte22 ON cte21.rn = cte22.rnx
SET CasoB.personsToGive = cte22.persons;

小提琴

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