我的第一个选择陈述是:
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 CID
中实体3的正确值。其他行也是如此。
我们有多个客户数据库都需要运行这个脚本,所以我不能轻松做到这一点,只看这两个并编写一些手动更新。如何编写此脚本以完成所有操作?
以下是对数据的更详细说明以及需要完成的工作:
答案 0 :(得分: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根本不应该在资产表中。至少,虽然不理想,但应该有一个约束来防止输入错误的值组合,例如从资产表到(group_key, entity_key)
上的资产组表的FK关系。这有其自身的问题,例如无法在组之间移动实体。该组不唯一地标识实体,因此它实际上不是密钥的一部分,应该被删除。
最终,您的group_keys是使用单个值替换每个(entity_key, group_id)
的代理。但是,然后重复资产表中的entity_key。这毫无意义。如果您的姓名为Joe Public
,并且您获得了一个唯一引用此全名的号码,例如28975,那么为什么您将自己称为Joe 28975
?无论是一个还是另一个。这个问题就是你可以说像Moe 28975
之类的东西根本没有提到任何人!然后,您必须查找人员编号28975的真实名字,并将Moe
更改为Joe
。这不是最佳的。
在您的情况下,已损坏的流程仅根据姓氏在表格中查找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被人类使用并且本身具有重要意义,所以它们不应该在很多行中反复重复。
答案 1 :(得分: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
)
答案 2 :(得分:0)
好的,所以我的一位同事在嘲笑我过于复杂的努力后提出了解决方案。这是查询:
很抱歉没有详细介绍这背后的业务逻辑。当时我并不认为这是相关的,但我发现现在是这样。欢呼所有,感谢您的投入和忍受一个蓬松的开发人员:)
哦,我的工作防火墙突然认为我正在尝试sql注入攻击,因此图像而不是代码。