【发布时间】:2017-02-07 10:53:19
【问题描述】:
这个问题与我在 Sparx 网站上SQL help in finding missing operations 提出的问题有关。他们建议我尝试 StackOverflow,所以我来了。在发布到 Sparx 网站之前,我曾尝试对这个问题进行大量研究。我对它进行了微调,使其更像是一般的 SQL 问题,而不是固定在我正在使用的工具上。
我不是 SQL 专家,所以请善待我!
情况
我有 2 个包含以下元素的表
Table t_object--------------Object_ID AutoNumberObject_Type TextName TextParentID Number
Table t_operation-----------------OperationID AutoNumberObject_ID NumberName Text
表 t_object 包含许多不同类型的项目。 Object_ID 是唯一键。我感兴趣的项目是 Object_Type = 'class' OR 'activity' OR 'activityparameter'。名称是项目的名称。 ParentID仅适用于'activityparameter'项,是'activityparameter'所属的'activity'的Object_ID。
表 t_operation 包含属于一个类的所有操作。 OperationID 是唯一键。 Object_ID 是这个操作如何链接到它在 t_object 中的类。
问题
在我们的系统中,所有类都有一个同名的活动,并且属于一个类的所有操作都有一个同名的活动参数属于该活动。
我正在尝试查找错误条目,其中 MyClass 类中的操作 MyOp 确实不在活动 MyClass 中具有同名的活动参数 MyOp。
使用下面的测试数据
t_object+-----------+-------------------+-------+----------+| Object_ID | Object_Type | Name | ParentID |+-----------+-------------------+-------+----------+| 1 | Class | c1 | 0 || 2 | Class | c2 | 0 || 3 | Activity | c1 | 0 || 4 | Activity | c2 | 0 || 5 | ActivityParameter | MyOp1 | 3 || 6 | ActivityParameter | MyOp2 | 3 || 7 | ActivityParameter | MyOp3 | 3 || 8 | ActivityParameter | MyOp1 | 4 || 9 | ActivityParameter | MyOp2 | 4 |+-----------+-------------------+-------+----------+
t_operation+-------------+-----------+-------+| OperationID | Object_ID | Name |+-------------+-----------+-------+| 1 | 1 | MyOp1 || 2 | 1 | MyOp2 || 3 | 2 | MyOp1 || 4 | 2 | MyOp2 || 5 | 2 | MyOp3 || 6 | 2 | MyOp4 |+-------------+-----------+-------+
以上表格代表如下
Operation c1::MyOp1 (from class c1)Operation c1::MyOp2 (from class c1)Operation c2::MyOp1 (from class c2)Operation c2::MyOp2 (from class c2)Operation c2::MyOp3 (from class c2)Operation c2::MyOp4 (from class c2)Activity parameter c1::MyOp1 (from activity c1)Activity parameter c1::MyOp2 (from activity c1)Activity parameter c1::MyOp3 (from activity c1)Activity parameter c2::MyOp1 (from activity c2)Activity parameter c2::MyOp2 (from activity c2)
我们可以看到以下错误
Operation c2::MyOp3 has no equivalent activity parameterOperation c2::MyOp4 has no equivalent activity parameterActivity parameter c1::MyOp3 has no equivalent operation
出于这个问题的目的,我对最终错误不感兴趣。当我得到“操作类::操作没有等效的活动参数”的 SQL 查询时,我将有逻辑来做相反的事情。
我尝试了 SQL 查询(我正在使用 Access 和 MySQL)。请注意,文本搜索不区分大小写。如果活动参数属于提到的活动,则 SELECT 末尾的 2 个 ID 应该相等。如果它们不同,则返回的活动参数属于不同的活动。这可以作为快速交叉检查。
SELECT o_class.name, o_operation.name, o_activity.name, o_actparam.name, o_activity.object_ID AS "activity ID", o_actparam.parentID AS "belongs to activity ID"
FROM
(((
t_object o_class
INNER JOIN t_object o_activity ON
( o_activity.name = o_class.name
AND
o_class.object_type = 'class'
AND
o_activity.object_type = 'activity'
)
)
INNER JOIN t_operation o_operation ON o_operation.object_id = o_class.object_id)
LEFT JOIN t_object o_actparam ON
( o_actparam.name = o_operation.name
AND
o_actparam.object_type = 'activityparameter'
AND
o_actparam.parentid = o_activity.object_id
)
)
WHERE
o_actparam.name is NULL
ORDER BY
o_class.name, o_operation.name, o_activity.name, o_actparam.name, o_activity.object_ID, o_actparam.parentID
上面的目的是得到一个类,然后是一个同名的activity,然后是属于这个类的所有操作,然后对于每个操作try and find一个activity此活动中具有相同名称的参数。任何不匹配的都应返回 NULL(因为它是 LEFT JOIN),因此 WHERE 语句显示没有相关活动参数的操作,即错误。
上述方法不起作用;我收到“不支持 JOIN 表达式”。
如果我取出“o_actparam.parentid = o_activity.object_id”,那么它根本不会返回任何结果。 这显然是错误的。我相信这是因为 LEFT JOIN 匹配第一个表达式,即“o_actparam.name = o_operation.name”,然后将任何其他表达式应用于该结果。所以它返回 10 行(c2::MyOp4 一个 NULL),但第二个表达式(o_actparam.object_type = 'activityparameter')然后丢弃 NULL(c2::MyOp4)。然后所有 9 个结果都被 WHERE 子句丢弃。
如果我将 LEFT JOIN 更改为
LEFT JOIN t_object o_actparam ON
( o_actparam.name = o_operation.name
AND
( o_actparam.object_type = 'activityparameter'
OR
o_actparam.object_type is NULL
)
)
)
然后我得到结果
c2::MyOp4
找不到 c2::MyOp3。这是因为操作 c2::MyOp3 与活动参数 c1::MyOp3 匹配(相同的活动参数名称,即使它属于错误的类/活动 c1)。 LEFT JOIN 比较忽略类/活动。请记住,如果我检查 'o_actparam.parentid = o_activity.object_id',那么我会得到“不支持 JOIN 表达式”。
如果我将 WHERE(并保留上述 LEFT JOIN)更改为
WHERE
o_actparam.parentid <> o_activity.object_id
OR
o_actparam.parentid is NULL
然后我得到结果
c1::MyOp1
c1::MyOp2
c2::MyOp1
c2::MyOp2
c2::MyOp3
c2::MyOp4
现在发现很多错误的项目,因为相同的活动参数名称存在于不同的活动中。 WHERE 来不及丢弃物品,但是,将 parentid 放在 LEFT JOIN 中给了我“不支持 JOIN 表达式”的错误。
在我的研究中,我注意到我可以在 ON 子句中连接表达式,例如
LEFT JOIN t_object o_actparam ON
o_actparam.name + o_actparam.object_type + o_actparam.parentid = o_operation.name + 'activityparameter' + o_activity.object_id
)
这里的想法是,如果 LEFT JOIN 在第一个表达式上起作用,然后过滤任何后续的表达式,然后将它们全部放在一起就可以满足我的要求。它还具有不需要到处都要求“OR xxx is NULL”的好处。它还强化了我正在寻找的东西,名称、对象类型和父对象的组合。当然,上述方法不起作用(或者我不会在这里问);它仍然给出了相同的“不支持 JOIN 表达式”。同样,删除“parentID”方面会产生错误的结果。
我希望我已经给出了详细的情况、测试用例、预期的答案、我的推理和我的研究,以表明这不仅仅是“我懒得自己解决,请帮忙”。我花了几天时间在谷歌上搜索并尝试了 SQL,但正如我所说,我不是 SQL 专家。
这里有人可以帮助我吗?
谢谢
达伦
【问题讨论】:
-
我找到了答案,所以我把它贴在这里,以防有人觉得它有用。