4

単一のテーブルの冗長な行を「マージ」する必要がある実稼働データベースがあります。

このテーブルの両方の行が、ID を除いて同じ値を持っていると仮定しましょう。

Table "PrimaryStuff"
ID | SomeValue
1  | "I have value"
2  | "I have value"
3  | "I am different"

また、多数の関連テーブルが存在すると仮定しましょう。「PrimaryStuff」テーブルで重複が作成されたため、多くの場合、これらの子テーブルに行が作成され、すべてが PrimaryStuff テーブルの単一のレコードに関連付けられる必要があります。 これらのテーブルの数と名前は私の管理下になく、実行時に動的に考慮する必要があります。IE: 他の人が私の知らないうちにデータベースを編集する可能性があるため、関連するレコードの名前や数さえわかりません。

Table "ForeignStuff"
ID | PrimaryStuffId | LocalValue
1| 1| "I have the correct FK"
2| 1| "I have the correct FK"
3| 2| "I should get pointed to an FK of 1"

PrimaryStuffの行 1 と 2 の重複を解決するには、関連するすべてのテーブルの FK を 1 に変更してから、PrimaryStuff の行 2 を削除したいと考えています。行 2 の主キーを 1 に変更すると、変更がカスケードアウトします。PrimaryStuff の一意のインデックスで重複キーになるため、これを行うことはできません。

お気軽に質問してください。わかりにくいことは何でも解決しようとします。

4

2 に答える 2

2

最初に、更新する必要がある行のリストを取得します (私が理解しているように、最小の ID で上位の ID をすべて置き換える必要があります)。

 SELECT MIN(ID) OVER (PARTITION BY SomeValue ORDER BY SomeValue, ID ASC) AS FirstID,
        ID,
        SOMEVALUE
 FROM PrimaryStuff

FirstID と ID が一致するものは削除できますが、これらは問題ではありません

SELECT FirstID, ID FROM
(
 SELECT MIN(ID) OVER (PARTITION BY SomeValue ORDER BY SomeValue, ID ASC) AS FirstID,
        ID,
        SOMEVALUE
 FROM PrimaryStuff
) T
WHERE FirstID != ID

これで、変更リストができました。これを更新ステートメントで使用して、一時テーブル (または以下で行ったように CTE) に配置できます。

WITH ChangeList AS
(
  SELECT FirstID, ID FROM
  (
   SELECT MIN(ID) OVER (PARTITION BY SomeValue ORDER BY SomeValue, ID ASC) AS FirstID,
        ID
   FROM PrimaryStuff
  ) T
  WHERE FirstID != ID
)
UPDATE ForeignStuff
SET PrimaryStuffId = ChangeList.FirstID
FROM ForeignStuff
JOIN ChangeList ON ForeignStuff.ID = ChangeList.ID

注意 - コードはテストされていないため、タイプミスがある可能性があります。

于 2013-09-17T15:38:00.010 に答える
1

SomeValue が既に存在する場合は既存の ID を使用して PrimaryStuff.SomeValue に一意の制約を適用するか、または SomeValue を PrimaryStuff の主キーにしないでください。それを PrimaryKey として使用すると、 SomeValue がまだそこに存在しない場合にのみ、レコードを PrimaryStuff に追加します。

最後に、そして最も簡単に言えば、SomeValue が常に他の人によって任意に定義されていて、彼らがあなたに与えたものを何でも受け取るのであれば、PrimaryStuff を完全に削除して、ユーザーが望むものをすべて ForeignStuff に入力できるようにしないのはなぜでしょうか? SomeValue の一意のリストが必要な場合は、メイン テーブルに基づいてビューを作成します。クエリを高速化する必要がある場合は、ForeignStuff.SomeValue フィールドにインデックスを追加します。

これは、ForeignStuff のような複数のテーブルがある場合の (未テストの) ビューです。

-- dynamically generate a distinct list of values of interest
select SomeValue from ForeignStuffA
union select SomeValue from ForeignStuffB
union select SomeValue from ForeignStuffC
-- and so on, the union applies distinct
于 2013-09-17T15:48:23.940 に答える