3

患者データを含むテーブルを匿名化するスクリプトに取り組んでいます。50,000 行の匿名データを含むテーブルを生成しました。

必要なのは、生成されたテーブルのデータで更新される患者テーブルの列の数です。

もちろん、テーブルの更新と別のテーブルからランダムな行を選択する方法についてはすでに読んでいます。私が理解できないのは、これを1つのクエリに組み合わせる方法です。

私は CTE を可能な解決策として見てきましたが、それがどのように機能するのかわかりません。私が抱えている主な問題の1つは、生成されたテーブルにキーが含まれていないことです.たとえそれがあったとしても、ランダムな行で値を更新する患者テーブルのすべての行を反復したいだけなので、関連するべきではありません.生成されたテーブルから。

私は次のものを持っています:

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


しかし、それは「ランダム」を1回だけ実行し、患者テーブルのすべての行を同じ値で埋めます。前に言ったように、それは 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します。FakeNameGeneratorID

于 2013-02-06T12:19:10.447 に答える
1

サブクエリ内でのランダムな並べ替えの使用に関するより詳細な Q&A がここにあります。しかし要するに、ランダムなデータから上位 1 つを選択してこれを機能させる方法を見つけることができませんでした。ソース データとサンプル データの両方に ( を使用してROW_NUMBER) ランダムな ID を与えてから、2 つを結合してランダムな更新を取得しました。

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

編集

OK、私のテストは比較できなかったようで、私の最初の考えはうまくいくでしょう。テストする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 の方法の問題は、最初のテーブルと同じかそれ以上の数の行が 2 番目のテーブルに必要になることです。

したがって、2 番目のテーブルと最初のテーブルのクロス結合を実行し、結果を最初のテーブルの行数に制限することができます。

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 に答える