从表中随机选择多行
我在SQL里有这张表:
CREATE TABLE mytable
(
id BIGINT,
color VARCHAR(10),
food VARCHAR(10),
sport VARCHAR(12),
animal VARCHAR(10)
) DISTRIBUTE ON (id);
INSERT INTO mytable (id, color, food, sport, animal) VALUES
( 1, 'red', 'pizza', 'soccer', 'dog'),
( 2, 'blue', 'sushi', 'tennis', 'cat'),
( 3, 'green', 'tacos', 'basketball', 'horse'),
( 4, 'yellow', 'pasta', 'golf', 'rabbit'),
( 5, 'pink', 'pizza', 'swimming', 'fox'),
( 6, 'orange', 'burger', 'soccer', 'bear'),
( 7, 'black', 'ramen', 'hockey', 'wolf'),
( 8, 'purple', 'tacos', 'cricket', 'cat'),
( 9, 'white', 'salad', 'tennis', 'dog'),
(10, 'brown', 'pizza', 'running', 'deer'),
(11, 'cyan', 'curry', 'boxing', 'tiger'),
(12, 'gray', 'sushi', 'soccer', 'horse'),
(13, 'teal', 'burger', 'baseball', 'owl'),
(14, 'maroon', 'pasta', 'golf', 'dog'),
(15, 'navy', 'tacos', 'rugby', 'frog');
我想从这张表中随机选取15行(也就是带放回的抽样)。
最终结果应该大致看起来像这样:
| resample_id | original_id | color | food | sport | animal |
|---|---|---|---|---|---|
| 1 | 7 | black | ramen | hockey | wolf |
| 2 | 3 | green | tacos | basketball | horse |
| 3 | 7 | black | ramen | hockey | wolf |
| 4 | 12 | gray | sushi | soccer | horse |
| 5 | 1 | red | pizza | soccer | dog |
| 6 | 15 | navy | tacos | rugby | frog |
| 7 | 7 | black | ramen | hockey | wolf |
| 8 | 9 | white | salad | tennis | dog |
| 9 | 3 | green | tacos | basketball | horse |
| 10 | 14 | maroon | pasta | golf | dog |
| 11 | 2 | blue | sushi | tennis | cat |
| 12 | 12 | gray | sushi | soccer | horse |
| 13 | 5 | pink | pizza | swimming | fox |
| 14 | 10 | brown | pizza | running | deer |
| 15 | 5 | pink | pizza | swimming | fox |
我想到的逻辑——生成对应要被选中的行的随机编号,然后再把它们与原表连接起来:
SELECT
g.i AS resample_id,
t.id AS original_id,
t.color, t.food,
t.sport,
t.animal
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY NULL) AS i,
CAST((RANDOM() * 15) AS BIGINT) + 1 AS pick_id
FROM mytable
LIMIT 15
) g
JOIN mytable t ON t.id = g.pick_id
ORDER BY g.i;
这会得到空的结果。
有人能帮我看看到底是哪里出错了吗?
解决方案
我会改为使用一个独立的源来生成随机数。这样即使数据集少于15行,也能确保得到15行。
下面的查询做了以下几件事:
- 生成源数据(15行)
- 生成一个数字表(64k行)
- 生成两组各20个随机数
- 选取这些随机抽样的行
CREATE TABLE mytable (
id BIGINT,
color VARCHAR(10),
food VARCHAR(10),
sport VARCHAR(12),
animal VARCHAR(10)
) DISTRIBUTE ON (id);
INSERT INTO mytable (id, color, food, sport, animal) VALUES
( 1, 'red', 'pizza', 'soccer', 'dog'),
( 2, 'blue', 'sushi', 'tennis', 'cat'),
( 3, 'green', 'tacos', 'basketball', 'horse'),
( 4, 'yellow', 'pasta', 'golf', 'rabbit'),
( 5, 'pink', 'pizza', 'swimming', 'fox'),
( 6, 'orange', 'burger', 'soccer', 'bear'),
( 7, 'black', 'ramen', 'hockey', 'wolf'),
( 8, 'purple', 'tacos', 'cricket', 'cat'),
( 9, 'white', 'salad', 'tennis', 'dog'),
(10, 'brown', 'pizza', 'running', 'deer'),
(11, 'cyan', 'curry', 'boxing', 'tiger'),
(12, 'gray', 'sushi', 'soccer', 'horse'),
(13, 'teal', 'burger', 'baseball', 'owl'),
(14, 'maroon', 'pasta', 'golf', 'dog'),
(15, 'navy', 'tacos', 'rugby', 'frog');
CREATE TABLE numbers (
id BIGINT NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO
numbers
WITH
n(d, base, ix, val) AS
(
VALUES
(0, 0, 0, 0),
(1, 1, 0, 1)
UNION ALL
SELECT
d+1, base*2, ix, base*2 + ix
FROM
(
SELECT
d, base, ix
FROM
n
UNION ALL
SELECT
d, base, base + ix
FROM
n
)
AS double_up(d, base, ix)
WHERE
d BETWEEN 1 AND 15
)
SELECT
val
FROM
n
;
WITH
sampler AS
(
SELECT
s.id AS set_id,
n.id AS sample_id,
FLOOR(
RANDOM()
*
(SELECT COUNT(*) FROM mytable)
+
1
)
AS sample_rn
FROM
numbers AS s
CROSS JOIN
numbers AS n
WHERE
s.id < 2
AND
n.id < 20
),
sorted AS
(
SELECT
ROW_NUMBER() OVER () AS rn,
mytable.*
FROM
mytable
)
SELECT
sampler.set_id,
sampler.sample_id,
original.id AS original_id,
original.color,
original.food,
original.sport,
original.animal
FROM
sampler
INNER JOIN
sorted AS original
ON original.rn = sampler.sample_rn
ORDER BY
sampler.set_id,
sampler.sample_id
;
| SET_ID | SAMPLE_ID | ORIGINAL_ID | COLOR | FOOD | SPORT | ANIMAL |
|---|---|---|---|---|---|---|
| 0 | 0 | 4 | yellow | pasta | golf | rabbit |
| 0 | 1 | 7 | black | ramen | hockey | wolf |
| 0 | 2 | 4 | yellow | pasta | golf | rabbit |
| 0 | 3 | 10 | brown | pizza | running | deer |
| 0 | 4 | 4 | yellow | pasta | golf | rabbit |
| 0 | 5 | 1 | red | pizza | soccer | dog |
| 0 | 6 | 11 | cyan | curry | boxing | tiger |
| 0 | 7 | 14 | maroon | pasta | golf | dog |
| 0 | 8 | 12 | gray | sushi | soccer | horse |
| 0 | 9 | 11 | cyan | curry | boxing | tiger |
| 0 | 10 | 8 | purple | tacos | cricket | cat |
| 0 | 11 | 10 | brown | pizza | running | deer |
| 0 | 12 | 10 | brown | pizza | running | deer |
| 0 | 13 | 1 | red | pizza | soccer | dog |
| 0 | 14 | 1 | red | pizza | soccer | dog |
| 0 | 15 | 12 | gray | sushi | soccer | horse |
| 0 | 16 | 8 | purple | tacos | cricket | cat |
| 0 | 17 | 3 | green | tacos | basketball | horse |
| 0 | 18 | 12 | gray | sushi | soccer | horse |
| 0 | 19 | 15 | navy | tacos | rugby | frog |
| 1 | 0 | 3 | green | tacos | basketball | horse |
| 1 | 1 | 3 | green | tacos | basketball | horse |
| 1 | 2 | 8 | purple | tacos | cricket | cat |
| 1 | 3 | 8 | purple | tacos | cricket | cat |
| 1 | 4 | 11 | cyan | curry | boxing | tiger |
| 1 | 5 | 15 | navy | tacos | rugby | frog |
| 1 | 6 | 15 | navy | tacos | rugby | frog |
| 1 | 7 | 9 | white | salad | tennis | dog |
| 1 | 8 | 10 | brown | pizza | running | deer |
| 1 | 9 | 7 | black | ramen | hockey | wolf |
| 1 | 10 | 10 | brown | pizza | running | deer |
| 1 | 11 | 8 | purple | tacos | cricket | cat |
| 1 | 12 | 9 | white | salad | tennis | dog |
| 1 | 13 | 10 | brown | pizza | running | deer |
| 1 | 14 | 3 | green | tacos | basketball | horse |
| 1 | 15 | 11 | cyan | curry | boxing | tiger |
| 1 | 16 | 7 | black | ramen | hockey | wolf |
| 1 | 17 | 9 | white | salad | tennis | dog |
| 1 | 18 | 13 | teal | burger | baseball | owl |
| 1 | 19 | 11 | cyan | curry | boxing | tiger |
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。