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 的资产。我们有一个错误,它会根据非唯一字段抓取第一条记录。因此,如果我有两个名为“Group 1”的组,但它们存在于不同的父类别中,那么根据“Group 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。其他行也是如此。

我们有多个客户数据库都需要运行这个脚本,所以我不能做简单的事情,只看这两个并编写一些手动更新。我如何编写脚本来完成这一切?

以下是对数据的更详细说明以及需要做什么:

  • assetgroup 表将每个资产链接到一个 group_id,该 group_id 完全由 group_key 确定,该 group_key 在表中是唯一的。
  • 每个资产组 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 表中。至少,虽然不理想,但应该有一个约束来防止输入不正确的值组合,例如从 assets 表到 assetsgroup 表的 FK 关系(group_key, entity_key)。这有其自身的问题,例如无法在组之间移动实体。该组不唯一标识实体,因此它确实不是密钥的一部分,应该被删除。

最终,您的 group_keys 是(entity_key, group_id)用单个值替换每个的代理项。但随后您在 assets 表中重复 entity_key。这根本没有意义。如果您的名字是Joe Public,并且您被分配了一个唯一指代这个全名的数字,例如 28975,那么您为什么要称自己为Joe 28975?要么一个,要么另一个。这样做的问题是你可以说Moe 28975根本不涉及任何人的事情!然后您必须查找人号 28975 的真实名字,然后更改MoeJoe。这不是最优的。

在您的情况下,损坏的进程Public仅根据姓氏在表中查找并提取相应的数字 11645,给出Joe 11645另一个无效组合:

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

因此,您必须查找11645的姓氏,并找到 的正确数字Joe。我希望这有助于说明这个方案是如何混淆的。

我还想温和地反对您表格中的列顺序。一般来说,至少对我来说,将父列放在子列之前是最有意义的。将子列放在首位是令人困惑的(尤其是没有解释)。后缀id在数据库中几乎普遍用于表示内部标识符。group_id看到并意识到它是一个文本字符串而不是数字,这有点令人不安。事实上,这是另一种非规范化。如果您想将 group_id 重命名WAREHOUSE为,WAREHOUSE 1因为您要添加一个WAREHOUSE 2? 现在您必须更新引用它的所有行中的值。显然,group_ids 是由人类使用的,并且它们本身具有重要意义,因此它们不应该在许多行中一遍又一遍地重复。

于 2012-07-10T19:09:54.163 回答
1

我认为这样的事情会起作用(我自己无法真正检查)。

我强烈建议您在尝试之前将其包装在事务中:

    with correctGroup(groupKey, entityKey) as (
        SELECT distinct t1.Group_key, t1.entity_key
        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)
    update  assetList
    from    assetList al join correctGroup cg on al.entity_key = cg.entitykey
    set     group_key = groupKey
    Where Not Exists (
                    Select 1
                    From assetgroup As AG
                    Where AG.group_key = AL.group_key
                        And AG.entity_key = AL.entity_key
                    )
于 2012-07-10T17:14:11.240 回答
0

好的,所以我的一位同事在嘲笑我过于复杂的努力后想出了解决方案。这是查询:

在此处输入图像描述

很抱歉没有详细介绍这背后的业务逻辑。当时我认为这无关紧要,但我发现现在是。干杯,感谢您的投入并忍受一个愤怒的开发人员:)

哦,我的工作防火墙突然认为我正在尝试 sql 注入攻击,因此是图像而不是代码。

于 2012-07-10T18:17:15.220 回答