【问题标题】:SQL to select randomly intercalated grouped resultsSQL 选择随机插入的分组结果
【发布时间】:2017-08-29 16:47:03
【问题描述】:

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

我们正在使用 SQLite。

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

身份证猫 --- --- 076 C 第753章 503一 081乙 第335章 475乙 第643章 995 一个 105 E 第549章 第553章 第871章 第064章 720 天 119 一个

上面的例子展示了 3 组 os 结果,它们的行是随机选择的,其排序也是随机的。

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

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

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

【问题讨论】:

  • 您可以使用UNION子句向服务器发出单个查询,您可以找到一个例子here@rubens-amaral
  • 感谢@DanIonescu 的建议,但是我的折叠随机要求呢?很抱歉,但使用 UNION 我无法弄清楚如何实现这一点。
  • 您是否希望 3 组结果的类别每次都是唯一的,或者可能 B、D、A、C、B 是可以接受的@rubens-amaral?
  • 是的,每个组都应该有唯一的类别,所以 B,D,A,C,B 是不可接受的

标签: sql sqlite random group-by sql-order-by


【解决方案1】:

您可以使用五个临时表将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;

【讨论】:

  • 嗨@CL,感谢您的建议,但“ORDER BY nr, random()”出现错误“第二个 ORDER BY 术语与结果集中的任何列都不匹配”。我对此stackoverflow.com/questions/43284268/… 提出了一个新问题
  • 糟糕;现已修复。
【解决方案2】:

开发了一种获得我们需要的结果的方法:连续的行块,每个块没有“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;

【讨论】:

    【解决方案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    
    

    【讨论】:

    • 再次感谢@DanIonescu。实际上,查询根本不应该有重复的结果行。您的查询可以防止每个块内的重复,这没关系,但是当 UNION 应用时,可能会发生重复。也许没有解决方案,这真的是一个挑战。我们正在尝试使用 WHERE 子句和/或 JOINS 来处理您的建议,以便每个块不再提取从前一个块中提取的任何检索数据,但仍然没有运气
    猜你喜欢
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多