CTE 中的 SQLite RANDOM() 函数

SQLite RANDOM() function in CTE

我在 SQLite 中发现了 RANDOM() 函数的行为,这似乎不正确。

我想使用随机 RANDOM() 和 CASE 生成随机组。但是,看起来 CTE 的行为方式不正确。

首先,让我们创建一个table

DROP TABLE IF EXISTS tt10ROWS;
CREATE TEMP TABLE tt10ROWS (
    some_int INTEGER);

INSERT INTO tt10ROWS VALUES
    (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
SELECT * FROM tt10ROWS;

不正确的行为

WITH 
    -- 2.a add columns with random number and save in CTE
    STEP_01 AS (
        SELECT
            *,
            ABS(RANDOM()) % 4 + 1 AS RAND_1_TO_4
        FROM tt10ROWS)
        
    -- 2.b - get random group
select
    *,
    CASE 
        WHEN RAND_1_TO_4 = 1 THEN 'GROUP_01'
        WHEN RAND_1_TO_4 = 2 THEN 'GROUP_02'
        WHEN RAND_1_TO_4 = 3 THEN 'GROUP_03'
        WHEN RAND_1_TO_4 = 4 THEN 'GROUP_04' 
        END AS GROUP_IT
from STEP_01;

使用这样的查询我们得到 table,它为 RAND_1_TO_4 列生成正确的值,但是 GROUP_IT 列不正确。我们可以看到,组不匹配,有些组甚至丢失。

正确行为

我通过创建临时 table 而不是使用 CTE 找到了解决此类问题的方法。有帮助。

-- 1.a - add column with random number 1-4 and save as TEMP TABLE
drop table if exists ttSTEP01;
CREATE TEMP TABLE ttSTEP01 AS
        SELECT
            *,
            ABS(RANDOM()) % 4 + 1 AS RAND_1_TO_4
        FROM tt10ROWS;

-- 1.b - get random group
select
    *,
    CASE 
        WHEN RAND_1_TO_4 = 1 THEN 'GROUP_01'
        WHEN RAND_1_TO_4 = 2 THEN 'GROUP_02'
        WHEN RAND_1_TO_4 = 3 THEN 'GROUP_03'
        WHEN RAND_1_TO_4 = 4 THEN 'GROUP_04' 
        END AS GROUP_IT
from ttSTEP01;

问题

这种行为背后的原因是什么,其中 GROUP_IT 列未正确生成?

如果您查看使用 EXPLAIN 的错误查询生成的字节码,您会发现每次引用 RAND_1_TO_4 列时,其值为 re-calculated 和一个使用了新的随机数(我怀疑但不是 100% 确定这与 random() 是一个 non-deterministic 函数的方式有关)。空值适用于 CASE 测试中的 none 最终为真的那些时间。

当您插入一个临时 table 然后将其用于其余部分时,值当然会保持静态并且它会按预期工作。