MariaDB CTE 的非确定性结果

问题描述 投票:0回答:1

我正在编写一个使用随机函数的查询,本质上可以归结为下面的示例:

with test_a as (
    select 
        rand()
), test_b as (
    select
        *
    from 
        test_a
)

select
    *
from
    test_a
    
union all

select
    *
from
    test_b

使用此代码,我得到随机值的两个不同结果,即:

0.013195173827181732
0.4233234193393247

这种行为对我来说似乎很奇怪,为什么

test_a
的结果在其他查询中没有持续存在?这是否意味着
test_a
被执行了两次?我认为 CTE 的目的是封装结果,以便在以后的 SQL 中进行简单快速的引用,因此如果它包含复杂的代码,它不会造成性能损失。如果执行两次,复制和粘贴子查询有什么不同?

我来自 Postgres 背景,出于理智,我测试了完全相同的代码(将

rand()
切换到
random()
)并得到了我预期的结果:

0.1106535559017996
0.1106535559017996

任何帮助将不胜感激 - 有什么方法可以将服务器/查询配置为确定性的吗?

sql mysql mariadb common-table-expression
1个回答
0
投票

我更喜欢这样的逻辑:参与 UNION 的每个 select 都是一个独立的对象。最终结果是这些独立结果集的系列。所以,我更喜欢在有或没有 cte 的情况下得到不同的结果。

我认为你使用cte的sql应该与

相同
select  rand() as rnd  union all
select  rand() as rnd  

但是,不同的数据库引擎 - 不同的结果......

玛丽亚数据库

select  rand() as rnd  union all
select  rand() as rnd  
rnd
0.7478762015214899
0.3074731568875473
WITH
  test_a as ( select  rand() as rnd ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b
rnd
0.29373721060691144
0.5462666131055602

小提琴

甲骨文

select  dbms_random.value() as rnd  union all
select  dbms_random.value() as rnd  
RND
.79263673293668402832745133398730975957
.71377343882776975895876411444816767274
WITH
  test_a as ( select  dbms_random.value() as rnd ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b
RND
.21692968397094372775858765087511007339
.23820817422791858668852994820400455145

小提琴

SQL Server

select  rand() as rnd  union all
select  rand() as rnd  
rnd
0.0014175088531201
0.522054389378644
WITH
  test_a as ( select  rand() as rnd ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b
rnd
0.160377090511521
0.276885005741768

小提琴

MySQL

select  rand() as rnd  union all
select  rand() as rnd  
rnd
0.4326515648818124
0.42990146431131426
WITH
  test_a as ( select  rand() ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b
兰德()
0.851552657644779
0.851552657644779

小提琴

SQLite

select  random() as rnd  union all
select  random() as rnd  
rnd
4865739885880678000
7043813893986921000
WITH
  test_a as ( select  random() ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b

|随机() | | :---------| | -5516896696497172000 | | -5516896696497172000 | 小提琴

Postgres

select  random() as rnd  union all
select  random() as rnd  
rnd
0.5080853115712636
0.6200751818051424
WITH
  test_a as ( select  random() ), 
  test_b as ( select  *  from  test_a )
select   *  from  test_a    
union all
select   *  from  test_b
随机
0.5410845640785207
0.5410845640785207

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.