首页 > 解决方案 > 评估每一行的随机函数

问题描述

我有以下sql:

SELECT SERIES.TIME AS TIME
FROM GENERATE_SERIES(
             CAST('now' AS TIMESTAMP) - cast('1 month' AS INTERVAL),
             CAST('now' AS TIMESTAMP),
             CAST('1 day' AS INTERVAL)
         ) AS SERIES (TIME)
         CROSS JOIN
         (SELECT * FROM GENERATE_SERIES(1, (floor(random() * 10)::int))) as RANDOM_TABLE

这应该会生成一系列间隔为一小时的日期。我现在试图得到的是每天随机散开。我注意到在上面的 sql 语句random()中只评估一次,即使它在子查询中。

现在没有CROSS JOIN我得到:

| 2019-02-13 |
| 2019-02-14 |
| 2019-02-15 |

我现在得到CROSS JOIN例如:

| 2019-02-13 |
| 2019-02-13 |
| 2019-02-13 |
| 2019-02-14 |
| 2019-02-14 |
| 2019-02-14 |
| 2019-02-15 |
| 2019-02-15 |
| 2019-02-15 |

我想要的是每次扇出时都有一个随机数。例如:

| 2019-02-13 |
| 2019-02-14 |
| 2019-02-14 |
| 2019-02-14 |
| 2019-02-14 |
| 2019-02-15 |
| 2019-02-15 |
| 2019-02-15 |

我如何需要修改我的查询来实现这一点?

标签: sqldatabasepostgresql

解决方案


问题是过早优化。Postgres“忘记”了random()易变的,每次都应该调用。

这是一个修复:

SELECT SERIES.TIME AS TIME
FROM (SELECT s.time, (floor(random() * 10)::int) as num
      FROM GENERATE_SERIES(now() - interval '1 month' , now(), interval '1 day') s(time)
         ) AS SERIES (TIME)
         CROSS JOIN LATERAL
         GENERATE_SERIES(1, num) as RANDOM_TABLE

还有一个db<>fiddle

请注意,我做了一些看起来更像“Postgres”的替换——使用now(),interval等等来进行日期算术,而不是转换字符串。


推荐阅读