【问题标题】:SQLite recalculates random() multiple times in subquery or CTESQLite 在子查询或 CTE 中多次重新计算 random()
【发布时间】:2021-02-26 02:51:42
【问题描述】:

如果我运行以下查询:

WITH cte AS(SELECT random() AS rand)
SELECT rand,rand FROM cte;

rand计算一次,结果中出现两次相同的值。

如果我用一张桌子运行它:

DROP TABLE IF EXISTS data;
CREATE TABLE data(n int);
INSERT INTO data(n) VALUES(1),(2),(3),(4),(5);
WITH cte AS(SELECT random() AS rand FROM data)
SELECT rand,rand FROM cte;

或者,如果您更喜欢递归 CTE:

WITH 
    data AS (SELECT 1 AS n UNION ALL SELECT 1+n FROM data WHERE n<5),
    cte AS(SELECT random() AS rand FROM data)
SELECT rand,rand FROM cte;

rand 的值会针对每个实例重新计算,因此结果集中的每一行都有两个不同的值。见http://sqlfiddle.com/#!5/73fd4/1

我预计random() 会为每一行重新计算,但我没想到rand 值会在 CTE 之后重新计算。

我认为这不是标准行为,而且肯定不是 PostgreSQL、SQL Server 和 MySQL 的工作方式。

如何让 SQLite 每次迭代只计算一次 rand 值?

【问题讨论】:

标签: sqlite random subquery common-table-expression


【解决方案1】:

我可以为您提供以下解决方法,您可以按照自己的方式行事:

WITH data AS (
    SELECT 1 AS n, random() AS rand
    UNION ALL SELECT 1 + n, random()
    FROM data WHERE n < 5
)

SELECT rand, rand FROM data;

Demo

这种方法只是在递归 CTE 中直接调用random()。无论出于何种原因,SQLite 本身似乎都不太聪明,并试图缓存对 random() 的初始调用。

【讨论】:

  • 我不应该包含递归 CTE。我真正想做的是为真实表的每一行设置一个随机值,然后多次使用该值。然而,奇怪的是,将 random() 放在 CTE 中会计算一次,但不会使用真实的表。
  • @Manngo ...如果使用 CTE 可以解决问题,那么它至少是一个有效的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-18
  • 2023-04-07
  • 1970-01-01
  • 2020-10-10
相关资源
最近更新 更多