3

我正在编写一个脚本来匿名化包含患者数据的表格。我生成了一个包含 50,000 行匿名数据的表。

我需要的是患者表中的一些列,这些列要使用生成表中的数据进行更新。

当然,我已经阅读了有关更新表格以及如何从另一个表格中选择随机行的信息。我不知道如何在一个查询中组合它。

我已经将 CTE 视为一种可能的解决方案,但我不明白它是如何工作的。我遇到的主要问题之一是生成的表中没有任何键,即使它有它也不应该是相关的,因为我只想迭代患者表的所有行,用随机行更新其值从生成的表中。

我有以下内容:

Update Patients
Set Patients.pat_FirstName = fn.GivenName,
     pat_LastName = fn.SurName, 
     pat_StreetName = fn.StreetAddress,
     pat_PostalCode = fn.ZipCode,
     pat_City = fn.City,
     pat_DateOfBirth = fn.BirthDay,
from
     ( Select Top 1,
     GivenName, 
     SurName,
     StreetAddress,
     ZipCode,
     City,
     Birthday
from FakeNameGenerator tablesample(1000 rows)) as fn


但这只会执行一次“随机”,用相同的值填充患者表中的每一行。就像我之前说的,它可以(应该??)用 CTE(理货?)表解决,但是如何解决呢?

我快要掌握 C# 了,只需编写该死的东西......

4

3 回答 3

3

另一种方法是向表中添加一个连续的数字FakeNameGenerator

ALTER TABLE FakeNameGenerator ADD ID INT NOT NULL IDENTITY(1,1)

CREATE UNIQUE NONCLUSTERED INDEX ix ON FakeNameGenerator(ID)

那么它就变成了生成1到50,000之间的随机数的问题

UPDATE P
SET P.pat_FirstName = F.GivenName /*...*/
FROM Patients P
INNER LOOP JOIN FakeNameGenerator F ON F.ID = (1 +  ABS(CRYPT_GEN_RANDOM(8)%50000))

INNER LOOP JOIN提示强制使用嵌套循环连接Patients作为驱动表。它FakeNameGenerator为每一行寻找重新评估ID要寻找的。

于 2013-02-06T12:19:10.447 回答
1

这里有关于在子查询中使用随机排序的更详细的问答。但简而言之,我找不到通过从随机数据中选择前 1 个来使其正常工作的方法。我给源数据和样本数据都提供了一个随机 id(使用ROW_NUMBER),然后加入两者以获得随机更新:

WITH PatientCTE AS
(   SELECT  PatientID,
            pat_FirstName,
            pat_LastName,
            pat_StreetName,
            pat_PostalCode,
            pat_City,
            pat_DateOfBirth,
            rn = ROW_NUMBER() OVER(ORDER BY NEWID())
    FROM    Patients
), SampleData AS
(   SELECT  GivenName, 
            SurName, 
            StreetAddress, 
            ZipCode, 
            City, 
            Birthday,
            rn = ROW_NUMBER() OVER(ORDER BY NEWID())
    FROM    FakeNameGenerator
)
UPDATE  PatientCTE
SET     Patients.pat_FirstName = fn.GivenName,
        pat_LastName = fn.SurName, 
        pat_StreetName = fn.StreetAddress,
        pat_PostalCode = fn.ZipCode,
        pat_City = fn.City,
        pat_DateOfBirth = fn.BirthDay,
FROM    PatientCTE p
        INNER JOIN SampleData fn
            ON fn.rn = p.rn

编辑

好的,所以看来我的测试没有可比性,我最初的想法是可行的。没有 DDL 和数据来测试我不能确定,但​​这应该工作:

UPDATE  Patients
SET     Patients.pat_FirstName = fn.GivenName,
        pat_LastName = fn.SurName, 
        pat_StreetName = fn.StreetAddress,
        pat_PostalCode = fn.ZipCode,
        pat_City = fn.City,
        pat_DateOfBirth = fn.BirthDay,
FROM    Patients
        CROSS APPLY
        (   SELECT  TOP 1 
                    GivenName, 
                    SurName, 
                    StreetAddress, 
                    ZipCode, 
                    City, 
                    Birthday
            FROM    FakeNameGenerator TABLESAMPLE(1000 ROWS)
            ORDER BY NEWID(), Patients.Patient_ID
        ) fn
于 2013-02-06T10:58:03.177 回答
0

作为一个额外的想法,GarethD 方法的问题在于,它需要第二个表中的行数与第一个表中的行数更多或相同。

因此,您可以将第二个表与第一个表进行交叉连接,并将结果限制为第一个表中的行数。

WITH PatientCTE AS
(
    SELECT  
         PatientID 
        ,pat_FirstName 
        ,pat_LastName 
        ,pat_StreetName 
        ,pat_PostalCode 
        ,pat_City 
        ,pat_DateOfBirth 
        ,rn = ROW_NUMBER() OVER(ORDER BY NEWID()) 
    FROM Patients
)
, SampleData AS
(
    SELECT TOP (SELECT COUNT(*) FROM PatientCTE )  
             GivenName 
            ,SurName 
            ,StreetAddress 
            ,ZipCode 
            ,City 
            ,Birthday 
            ,rn = ROW_NUMBER() OVER(ORDER BY NEWID())
    FROM FakeNameGenerator 

    CROSS JOIN PatientCTE 
)

UPDATE p
SET      p.pat_FirstName = fn.GivenName 
        ,p.pat_LastName = fn.SurName 
        ,p.pat_StreetName = fn.StreetAddress 
        ,p.pat_PostalCode = fn.ZipCode 
        ,p.pat_City = fn.City 
        ,p.pat_DateOfBirth = fn.BirthDay 
FROM PatientCTE AS p

INNER JOIN SampleData AS fn
    ON fn.rn = p.rn
于 2013-09-20T14:21:31.160 回答