SQL 到 select 随机插入的分组结果

SQL to select randomly intercalated grouped results

对于具有 ID 和类别列的 table,我们将有一个包含 5 个值的类别域,例如 A、B、C、D 和 E。

我们正在使用 SQLite。

我们的目标是有一个查询,该查询带来许多随机选择和随机排序的插入分组行(在每组 5 行内),例如

ID    CAT
---   ---
076    C
753    D
503    A 
081    B 
335    E

475    B
643    D
995    A
105    E
549    C

553    E
871    B
064    C
720    D
119    A

上面的示例显示了 3 组 os 结果,whose 行是随机选择的,whose 排序也是随机的。

目前我们正在使用 5 个查询(每个类别一个)提取结果,然后根据应用程序代码对所有内容进行排序。

SELECT * FROM table WHERE cat = 'A' ORDER BY RANDOM() LIMIT 3;

如果有人通过使用单个查询提出更好的解决方案,我们将不胜感激。

您可以将以下查询与 3 个并集一起使用,它不是很短,但它确实有效:

SELECT randomized.id, randomized.cat
FROM (
    SELECT randomized.id, randomized.cat
    FROM (
        SELECT id,cat FROM `table_test` ORDER BY RANDOM() 
        ) AS randomized
    GROUP BY cat
    ORDER BY RANDOM()
    ) AS randomized
UNION ALL
SELECT randomized.id, randomized.cat
FROM (
    SELECT randomized.id, randomized.cat
    FROM (
        SELECT id,cat FROM `table_test` ORDER BY RANDOM() 
        ) AS randomized
    GROUP BY cat
    ORDER BY RANDOM()
    ) AS randomized
UNION ALL
SELECT randomized.id, randomized.cat
FROM (
    SELECT randomized.id, randomized.cat
    FROM (
        SELECT id,cat FROM `table_test` ORDER BY RANDOM() 
        ) AS randomized
    GROUP BY cat
    ORDER BY RANDOM()
    ) AS randomized    

您可以使用五个临时表为每个类别中的行分配 autoincrementing ID:

CREATE TEMPORARY TABLE a(nr INTEGER PRIMARY KEY, id);
CREATE TEMPORARY TABLE b(nr INTEGER PRIMARY KEY, id);
...
INSERT INTO temp.a(id) SELECT id FROM MyTable WHERE cat = 'A' ORDER BY random();
INSERT INTO temp.b(id) SELECT id FROM MyTable WHERE cat = 'B' ORDER BY random();
...

然后可以把五个表合并起来,让nr值相同的行排在一起:

SELECT nr, id, 'A' AS cat, random() AS r FROM temp.a
UNION ALL
SELECT nr, id, 'B',        random()      FROM temp.b
UNION ALL
...
ORDER BY nr, r;

开发了一种方法来获得我们需要的结果:连续的行块,每个块没有 'cat' 重复,并且根本没有 'id' 重复。

它更偏向于数学而不是面向查询,但无论如何它适合我们的需要。

CREATE TEMPORARY TABLE a(nr INTEGER PRIMARY KEY, sort, id, cat);

INSERT INTO temp.a(id, cat) SELECT id, cat FROM tabela WHERE cat = 'A' ORDER BY random() limit 3;
INSERT INTO temp.a(id, cat) SELECT id, cat FROM tabela WHERE cat = 'B' ORDER BY random() limit 3;
INSERT INTO temp.a(id, cat) SELECT id, cat FROM tabela WHERE cat = 'C' ORDER BY random() limit 3;
INSERT INTO temp.a(id, cat) SELECT id, cat FROM tabela WHERE cat = 'D' ORDER BY random() limit 3;
INSERT INTO temp.a(id, cat) SELECT id, cat FROM tabela WHERE cat = 'E' ORDER BY random() limit 3;

UPDATE temp.a SET sort=100 where nr=1;
UPDATE temp.a SET sort=92+(select abs(random()%(2))*16) where nr=4;
UPDATE temp.a SET sort=88+(select abs(random()%(4))*8) where nr=7;
UPDATE temp.a SET sort=86+(select abs(random()%(8))*4) where nr=10;
UPDATE temp.a SET sort=85+(select abs(random()%(16))*2) where nr=13;

UPDATE temp.a SET sort=200 where nr=2;
UPDATE temp.a SET sort=192+(select abs(random()%(2))*16) where nr=5;
UPDATE temp.a SET sort=188+(select abs(random()%(4))*8) where nr=8;
UPDATE temp.a SET sort=186+(select abs(random()%(8))*4) where nr=11;
UPDATE temp.a SET sort=185+(select abs(random()%(16))*2) where nr=14;

UPDATE temp.a SET sort=300 where nr=3;
UPDATE temp.a SET sort=292+(select abs(random()%(2))*16) where nr=6;
UPDATE temp.a SET sort=288+(select abs(random()%(4))*8) where nr=9;
UPDATE temp.a SET sort=286+(select abs(random()%(8))*4) where nr=12;
UPDATE temp.a SET sort=285+(select abs(random()%(16))*2) where nr=15;

SELECT id, cat FROM temp.a ORDER BY sort;

DROP TABLE a;