0

私の最初の選択ステートメントはこれです:

 Select AL.asset_key, AL.group_key, AL.entity_key
From assetlist As AL
Where Not Exists    (
                Select 1
                From assetgroup As AG
                Where AG.group_key = AL.group_key
                    And AG.entity_key = AL.entity_key
                )

このクエリの結果には、誤って group_key が割り当てられたアセットが表示されます。一意でないフィールドに基づいて最初のレコードを取得するバグがありました。したがって、「グループ 1」という名前の 2 つのグループがあり、それらが異なる親カテゴリに存在する場合、スクリプトは「グループ 1」の最初の一致に基づいて新しいレコードを書き込み、それがそのカテゴリのグループであるかどうかを確認しません。 . とにかく、修正されたので、クリーンアップスクリプトを実行しようとしています。上記のクエリの結果は、次のようになります。

 asset_key  group_key   entity_key
 352        25          3
 376        77          3
 378        77          3

私が持っている別のクエリは、正しい値がどうあるべきかを確認するために、group_key とエンティティ キーを比較することです。

SELECT distinct
t1.Group_key, t1.entity_key, t1.group_id
FROM assetgroup t1 
INNER JOIN assetgroup t2 ON t2.Group_ID = t1.Group_ID 
WHERE t2.Group_key != t1.Group_key
and t2.entity_key != t1.entity_key
and t2.Group_ID = t1.Group_ID
order by t1.group_id   

結果セットは次のようになります。

Group_key   entity_key  group_id
25          1           CID
58          2           CID
59          3           CID
77          2           GROUP 1
79          3           GROUP 1
29          4           RENTAL
51          6           RENTAL
53          1           WAREHOUSE
36          5           WAREHOUSE

両方の結果を見ると、group_key 25 は entity_key 3 に属していないことがわかります。そのため、アセットを更新する必要があります。group_key を正しい group_key 値 59 に変更します。これは、 group_id のエンティティ 3 の正しい値ですCID。他の行についても同様です。

このスクリプトを実行する必要がある複数の顧客データベースがあるため、簡単なことはできず、これら 2 つを見て、手動で更新を作成するだけです。これをスクリプト化してすべてを完了するにはどうすればよいですか?

以下は、データと何を行う必要があるかについてのより詳細な説明です。

  • assetgroup テーブルは、テーブル内で一意の group_key によって完全に決定される group_id に各アセットをリンクします。
  • 各アセット グループ group_key は、entity_key に関連付けられています。各 entity_key は、各 group_id に一度だけ存在します。
  • 資産テーブルには、group_key と entity_key がリストされていますが、entity_key は group_key によって完全に暗示されているはずです。
  • ただし、一部のアセット行には間違った group_key があり、間違った group_key と同じ group_id 内のそのエンティティの正しい group_key に更新する必要があります。
4

3 に答える 3

3

これがあなたが探しているクエリです。

UPDATE A
SET A.group_key = R.group_key
FROM
   Assets A
   INNER JOIN AssetGroup W -- Wrong
      ON A.group_key = W.group_key -- find group_id of wrong group_key
   INNER JOIN AssetGroup R -- Right
      ON A.entity_key = R.entity_key -- also W.entity_key = R.entity_key
      AND R.group_id = W.group_id -- wrong group_key still has right group_id
WHERE
   A.group_key <> R.group_key

entity_key は group_key を完全に暗示していますが、group_key は assets テーブルで繰り返されるため、データベース テーブルは非正規化されていることに注意してください。これは、業界のベスト プラクティスに反するデータベース設計のアンチ パターンです。group_key は、アセット テーブルに含めるべきではありません。理想的ではありませんが、少なくとも、上の assets テーブルから assetgroup テーブルへの FK リレーションシップなど、誤った値の組み合わせが入力されるのを防ぐ制約が必要(group_key, entity_key)です。これには、グループ間でエンティティを移動できなくなるなどの問題があります。グループはエンティティを一意に識別しないため、実際にはキーの一部ではなく、削除する必要があります。

最終的に、group_keys は、それぞれ(entity_key, group_id)を単一の値に置き換えるサロゲートです。ただし、資産テーブルで entity_key を繰り返します。これはまったく意味がありません。あなたの名前がJoe Publicで、このフルネームを一意に参照する番号 (たとえば 28975) が割り当てられた場合、なぜ自分自身を と呼ぶのでしょうJoe 28975か? どちらか、または他の。Moe 28975これに関する問題は、 which は誰にもまったく言及していないようなことを言うことができるということです! 次に、個人番号 28975 の REAL 名を調べて、に変更Moeする必要がありJoeます。これは最適ではありません。

あなたの場合、壊れたプロセスはPublic姓のみに基づいてテーブルを検索し、対応する番号11645を取得してJoe 11645、別の無効な組み合わせを与えました:

Last   First Number
------ ----- ------
Public Joe   29875
Public Moe   11645

11645そのため、 の姓を調べて、 の正しい番号を見つけなければなりませんでしJoeた。これが、このスキームがどのように混同されているかを示すのに役立つことを願っています.

また、テーブルの列の順序にも少し反対したいと思います。一般に、少なくとも私にとっては、親列を子列の前に配置するのが最も理にかなっています。子列を最初に置くのは混乱を招きます (特に説明なし)。そして接尾辞idは、内部識別子を意味するためにデータベースでほぼ普遍的に使用されています。group_idそれが数字ではなく文字列であることを見て、それを理解するのは少し不安です。実際、これは別の非正規化です。を追加するためにWAREHOUSEgroup_idの名前を変更したい場合はどうしますか? 次に、それを参照するすべての行の値を更新する必要があります。明らかに、group_id は人間によって使用され、それ自体に重要性があるため、多くの行で何度も繰り返されるべきではありません。WAREHOUSE 1WAREHOUSE 2

于 2012-07-10T19:09:54.163 に答える
0

わかりましたので、私の複雑すぎる努力を笑った後、私の同僚が解決策を思いつきました。クエリは次のとおりです。

ここに画像の説明を入力

この背後にあるビジネス ロジックについて詳しく説明できなくて申し訳ありません。当時は関係ないと思っていましたが、今では関係がありそうです。乾杯、入力とハフィー開発者に我慢してくれてありがとう:)

ああ、私の仕事のファイアウォールは突然、私がSQLインジェクション攻撃を試みていると考えているため、コードではなくイメージです。

于 2012-07-10T18:17:15.220 に答える