sqlite - CTE 中的 SQLite RANDOM() 函数
问题描述
我在 SQLite 中发现了 RANDOM() 函数的行为,这似乎不正确。
我想使用随机 RANDOM() 和 CASE 生成随机组。但是,看起来 CTE 的行为方式不正确。
首先,让我们创建一个表
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;
使用这样的查询,我们得到一个表,它为 RAND_1_TO_4 列生成正确的值,但 GROUP_IT 列不正确。我们可以看到,组不匹配,有些组甚至丢失。
正确的行为
我通过创建临时表而不是使用 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
引用该列时,都会重新计算其值并使用新的随机数(我怀疑但不是 100% 确定这有与如何random()
是非确定性函数有关)。CASE
空值适用于没有任何测试最终为真的那些时间。
当您插入临时表然后将其用于其余部分时,这些值当然保持静态并且按预期工作。
推荐阅读
- ios - 默认情况下,SwiftUI 文本替换在 TextField 视图上不起作用
- c - 我的代码将打印两次错误消息并仍然运行
- flutter - 如何以编程方式模拟 Flutter 中按钮的 onTap?
- regex - 使用 Regex 提取下一个语义发布版本
- php - 下拉列表中的PHP格式日期不起作用
- r - 尽管在调用中提供了值,但函数使用默认参数
- javascript - HTML5 本地存储 - 我可以为每个键存储多个值吗?如果不能,我可以使用什么替代方法?
- powershell - PowerShell - CSV - 多个标头和值 - Foreach - 使用标头和值
- android - BiometricPromptCompat:禁用虹膜/人脸识别(仅允许指纹)
- reactjs - React 中的 componentDidMount 函数