Kar*_*hic 5 postgresql amazon-redshift
update dataset1.test
set column4 = (select column1
from dataset2
order by random()
limit 1
)
Run Code Online (Sandbox Code Playgroud)
我必须更新第4列的dataset1,每一行都更新数据集2列中的一个随机条目。但是到目前为止,在上述查询中,我在dataset1的所有行中都只有一个随机条目,而我希望它都相同是随机的。
设定
让我们开始假设您的表数据如下。请注意,我假设dataset1有一个主键(它可以是一个复合键,但是为了简单起见,让我们将其设为整数):
CREATE TABLE dataset1
(
id INTEGER PRIMARY KEY,
column4 TEXT
) ;
CREATE TABLE dataset2
(
column1 TEXT
) ;
Run Code Online (Sandbox Code Playgroud)
我们在两个表中都填充了示例数据
INSERT INTO dataset1
(id, column4)
SELECT
i, 'column 4 for id ' || i
FROM
generate_series(101, 120) AS s(i);
INSERT INTO dataset2
(column1)
SELECT
'SOMETHING ' || i
FROM
generate_series (1001, 1020) AS s(i) ;
Run Code Online (Sandbox Code Playgroud)
完整性检查:
SELECT count(DISTINCT column4) FROM dataset1 ;
Run Code Online (Sandbox Code Playgroud)
| 计数| | ----:| | 20 |
我们将进行完整的改组。来自dataset2的值将被使用一次,并且不超过一次。
说明
为了进行更新column4以随机方式随机整理所有值,我们需要一些中间步骤。
首先,对于dataset1,我们需要创建一个元组列表(关系)(id, rn),它们只是:
(id_1, 1),
(id_2, 2),
(id_3, 3),
...
(id_20, 20)
Run Code Online (Sandbox Code Playgroud)
id_1... id_20上的ID 在哪里dataset1。它们可以是任何类型,不需要连续,也可以是复合的。
对于dataset2,我们需要创建的另一个列表(column_1,rn),如下所示:
(column1_1, 17),
(column1_2, 3),
(column1_3, 11),
...
(column1_20, 15)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第二列包含所有值1 .. 20,但被重新排序。
一旦我们建立了两种关系,我们就JOIN可以了ON ... rn。实际上,这会生成另一个带有的元组列表(id, column1),其中的配对是随机进行的。我们使用这些对进行更新dataset1。
真正的查询
可以通过使用一些CTE(WITH语句)来保持中间关系来完成所有工作(显然,我希望如此):
WITH original_keys AS
(
-- This creates tuples (id, rn),
-- where rn increases from 1 to number or rows
SELECT
id,
row_number() OVER () AS rn
FROM
dataset1
)
, shuffled_data AS
(
-- This creates tuples (column1, rn)
-- where rn moves between 1 and number of rows, but is randomly shuffled
SELECT
column1,
-- The next statement is what *shuffles* all the data
row_number() OVER (ORDER BY random()) AS rn
FROM
dataset2
)
-- You update your dataset1
-- with the shuffled data, linking back to the original keys
UPDATE
dataset1
SET
column4 = shuffled_data.column1
FROM
shuffled_data
JOIN original_keys ON original_keys.rn = shuffled_data.rn
WHERE
dataset1.id = original_keys.id ;
Run Code Online (Sandbox Code Playgroud)
请注意,该技巧是通过以下方式执行的:
row_number() OVER (ORDER BY random()) AS rn
Run Code Online (Sandbox Code Playgroud)
的row_number()窗函数,因为有行,从1开始这些号码被随机洗牌的,因为产生许多连续的数字OVER子句了所有的资料和随机进行排序。
检查
我们可以再次检查:
SELECT count(DISTINCT column4) FROM dataset1 ;
Run Code Online (Sandbox Code Playgroud)
| 计数| | ----:| | 20 |
SELECT * FROM dataset1 ;
Run Code Online (Sandbox Code Playgroud)
id | 专栏4 -:| :------------- 101 | 东西1016 102 | 东西1009 103 | 东西1003 ... 118 | 东西1012 119 | 东西1017 120 | 1011的东西
替代
请注意,也可以通过子替换(而不是CTE)来实现子查询。在某些情况下,这可能会提高性能:
UPDATE
dataset1
SET
column4 = shuffled_data.column1
FROM
(SELECT
column1,
row_number() OVER (ORDER BY random()) AS rn
FROM
dataset2
) AS shuffled_data
JOIN
(SELECT
id,
row_number() OVER () AS rn
FROM
dataset1
) AS original_keys ON original_keys.rn = shuffled_data.rn
WHERE
dataset1.id = original_keys.id ;
Run Code Online (Sandbox Code Playgroud)
然后再次...
SELECT * FROM dataset1;
Run Code Online (Sandbox Code Playgroud)
id | 专栏4 -:| :------------- 101 | 1011的东西 102 | 东西1018 103 | 东西1007 ... 118 | 东西1020 119 | 东西1002 120 | 东西1016
您可以检查整个安装和试验在dbfiddle 这里
注意:如果您对非常大的数据集执行此操作,请不要期望它非常快。改组非常大的纸牌非常昂贵。
在这种情况下,的值column4可以重复几次。
我可以想到的最简单的可能性(可能不是一种有效的方法,但很容易理解)是创建一个random_column1标记为的函数VOLATILE:
CREATE FUNCTION random_column1()
RETURNS TEXT
VOLATILE -- important!
LANGUAGE SQL
AS
$$
SELECT
column1
FROM
dataset2
ORDER BY
random()
LIMIT
1 ;
$$ ;
Run Code Online (Sandbox Code Playgroud)
并使用它来更新:
UPDATE
dataset1
SET
column4 = random_column1();
Run Code Online (Sandbox Code Playgroud)
这样,dataset2 可能根本不会使用from中的某些值,而其他值 将被多次使用。
dbfiddle 在这里
| 归档时间: |
|
| 查看次数: |
1061 次 |
| 最近记录: |