bel*_*daz 7 postgresql random subquery
在下面的示例中,我有一个表foo,我想从中随机选择每组的一行。
CREATE TABLE foo (
line INT
);
INSERT INTO foo (line)
SELECT generate_series(0, 999, 1);
Run Code Online (Sandbox Code Playgroud)
假设我想按 分组line % 10。我可以这样做:
SELECT DISTINCT ON (bin) bin, line
FROM (
SELECT line, line % 10 AS bin, random() x
FROM foo
ORDER BY x
) X
Run Code Online (Sandbox Code Playgroud)
我想做的是多次从每个垃圾箱中随机选择。我原以为我能和做到这一点generate_series(),并LATERAL
SELECT i, line, bin
FROM
(
SELECT generate_series(1,3) i
) m,
LATERAL
(SELECT DISTINCT ON (bin) bin, line
FROM (
SELECT line, line % 10 bin, random() x
FROM foo
ORDER BY x
) X
ORDER BY bin) Q
ORDER BY bin, i;
Run Code Online (Sandbox Code Playgroud)
但是,当我在 PostgreSQL 9.5 中执行此操作时,我发现每次迭代line的给定bin值都相同i,例如,
i;line;bin
1;530;0
2;530;0
3;530;0
1;611;1
2;611;1
3;611;1
...
Run Code Online (Sandbox Code Playgroud)
我很困惑,因为我认为包含 的子查询random()对于generate_series().
编辑:我意识到我可以通过生成更多组合并从中选择来实现相同的目标
SELECT DISTINCT ON (bin, round) round, bin, line
FROM (
SELECT line, line % 10 as bin, round
FROM foo, generate_series(1,3) round
ORDER BY bin, random()
) X;
Run Code Online (Sandbox Code Playgroud)
所以我的问题很简单,为什么第一种方法不起作用?
编辑:问题似乎是,如果子查询以某种方式相关(感谢@ypercube 的评论),则 LATERAL 仅充当 for 循环。因此,可以通过添加以下小的更改来修复我原来的方法
SELECT i, line, bin
FROM
(
SELECT generate_series(1,3) i
) m,
LATERAL
(
SELECT DISTINCT ON (bin) bin, line
FROM (
SELECT line, line % 10 bin, m.i, random() x -- <NOTE m.i HERE
FROM foo
ORDER BY x
) X
ORDER BY bin
LIMIT 3
) Q
ORDER BY bin, i;
Run Code Online (Sandbox Code Playgroud)
我会像这样编写查询,使用LIMIT (3)而不是DISTINCT ON.
本generate_series(0, 9)是用来获取所有不同的垃圾箱。(SELECT DISTINCT line % 10 FROM foo) AS g (bin)如果“bins”不是从 0 到 9 的所有整数,您可以改用:
SELECT
g.bin,
ROW_NUMBER() OVER (PARTITION BY g.bin ORDER BY d.x) AS i,
d.*
FROM
generate_series(0, 9) AS g (bin),
LATERAL
( SELECT f.*, random() x
FROM foo AS f
WHERE f.line % 10 = g.bin
ORDER BY x
LIMIT 3
) AS d
ORDER BY
bin, x ;
Run Code Online (Sandbox Code Playgroud)
此外,如果您不需要random()输出中的数字,您可以ORDER BY random()在子查询中使用并x从 select 和 order by 子句中删除- 或替换ORDER BY d.x为ORDER BY d.line.
| 归档时间: |
|
| 查看次数: |
492 次 |
| 最近记录: |