使用其他表中多个值的随机更新表

Posted

技术标签:

【中文标题】使用其他表中多个值的随机更新表【英文标题】:Update table using random of multiple values in other table 【发布时间】:2015-08-12 11:28:08 【问题描述】:

考虑这些数据:

CREATE TABLE #Data (DataID INT, Code VARCHAR(2), Prefix VARCHAR(3))

INSERT INTO #Data (DataID, Code)
VALUES (1, 'AA')
, (2, 'AA')
, (3, 'AA')
, (4, 'AA')
, (5, 'AA')
, (6, 'AA')

CREATE TABLE #Prefix (Code VARCHAR(2), Prefix VARCHAR(3))

INSERT INTO #Prefix (Code, Prefix)
VALUES ('AA', 'ABC')
, ('AA', 'DEF')
, ('AA', 'GHI')
, ('AA', 'JKL')

我想将#Data 中的Prefix 值设置为来自#Prefix 的随机Prefix 与匹配的Code

使用直接的inner join 只会导致使用一个值:

UPDATE D
SET Prefix = P.Prefix
FROM #Data AS D
INNER JOIN #Prefix AS P ON D.Code = P.Code

通过阅读此处的其他问题,建议使用NEWID() 作为随机排序的一种方式。将join 更改为:

SELECT TOP 1 subquery ordering by NEWID() 

仍然只为每一行选择一个值(尽管每次都是随机的):

UPDATE D
SET Prefix = (SELECT TOP 1 P.Prefix FROM #Prefix AS P WHERE P.Code = D.Code ORDER BY NEWID())
FROM #Data AS D

所以,我不确定如何从单个更新语句中为每个数据条目获取随机前缀。我可能会通过#Data 表进行某种循环,但我避免接触SQL 中的循环,我相信这会很慢。实际应用在上万条记录上,几十条码有几百个前缀。

【问题讨论】:

【参考方案1】:

这是怎么做的:

UPDATE d SET Prefix = ca.Prefix
FROM #Data d
CROSS APPLY(SELECT TOP 1 Prefix 
            FROM #Prefix p 
            WHERE d.DataID = d.DataID AND p.Code = d.Code ORDER BY NEWID()) ca

通知d.DataID = d.DataID。这是为了强制Sql Server 引擎重新评估#Data 表中每一行的子查询。

【讨论】:

效果很好,但是太脆弱了。使用 p.Somecolumn = p.Somecolumn 而不是外部引用 d.Somecolumn = d.Somecolumns 并且它停止工作。让 MS 的一些软件工程师想出一种创新方法来优化始终正确的条件,然后它就会停止工作。

以上是关于使用其他表中多个值的随机更新表的主要内容,如果未能解决你的问题,请参考以下文章

Oracle:使用其他表中的值进行更新

用于从 N 记录的其他表值更新值的 SQL 查询

如何根据与另一个表中的值的比较来更新列

随机名称表中的 SQL 更新

使用从同一个表中获取值的变量创建更新触发器的正确​​方法是啥?

如何使用 Java Spring Boot 在不插入新值的情况下更新表中的现有值