这个问题与我在Sparx网站上SQL help in finding missing operations提出的问题有关。他们建议我尝试StackOverflow,所以我在这里。在Sparx网站发布之前,我曾尝试对此问题进行大量研究。我稍微调整了它,使其更像是一个普通的SQL问题而不是我正在使用的工具。
我不是SQL大师,所以请对我好!
情况
我有2个表有以下元素
Table t_object
--------------
Object_ID AutoNumber
Object_Type Text
Name Text
ParentID Number
Table t_operation
-----------------
OperationID AutoNumber
Object_ID Number
Name Text
表t_object包含许多不同类型的项目。 Object_ID是唯一键。我感兴趣的项目是Object_Type =' class' OR'活动'或者'活动参数'。名称是项目的名称。 ParentID仅适用于' activityparameter' items是' 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 parameter
Operation c2::MyOp4 has no equivalent activity parameter
Activity parameter c1::MyOp3 has no equivalent operation
出于这个问题的目的,我对最终错误不感兴趣。当我获得&#34时的SQL查询时,操作类:: operation没有等效的活动参数"然后我会有相反的逻辑。
我尝试了SQL查询(我正在使用Access和MySQL)。请注意,文本搜索不区分大小写。如果activity参数属于上述活动,则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
上述目的是获得一个类,然后是一个同名的活动,然后是属于该类的所有操作,然后为每个操作尝试找到一个活动此活动中具有相同名称的参数。任何不匹配的都应返回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)。然后WHERE子句抛弃所有9个结果。
如果我将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匹配activityparmater 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中时,我不支持&#34; JOIN表达式&#34;错误。
在我的研究中,我注意到我可以在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在第一个表达式上工作,那么过滤掉任何后续表达式,然后将它们全部放在一起就可以做我想要的。它还具有不要求&#34; OR xxx为NULL&#34;到处都是。它还强化了我正在寻找的东西,名称,对象类型和父母的组合。当然上面没有工作(或者我不会在这里问);它仍然提供相同的&#34; JOIN表达式不支持&#34;。再次,删除&#34; parentID&#34;方面给出了错误的结果。
我希望我已经提供了详细的情况,测试案例,预期的答案,我的推理和我的研究,以证明这不仅仅是一个&#34;我自己也无法解决这个问题,请帮助& #34 ;.我花了几天谷歌搜索和尝试SQL,但正如我所说,我不是SQL专家。
有人能帮助我吗?
由于
达伦
答案 0 :(得分:0)
我找到了答案,所以我发布在这里以防有人发现它有用。感谢Sandra的帮助。
答案是我的问题LEFT JOIN试图访问早期表中的条目,但它看不到它们,因为我提到了2个不同的表。我不是SQL专家,因此我不知道正确的术语或确切原因。
无论如何,解决方案是将所有先前的表放入子查询中,然后获取新的单个表名。
注意,因为我使用Access,所以我被告知LEFT JOIN的ON部分之后的括号是必不可少的,因为我加入了一个常量值('activityparameter')。
所需的更改是插入
(SELECT * FROM
在前2个表之前。请注意,这要求我将带有3个括号的单行分成2行,因为SELECT需要在第一个括号之后。
之后添加额外的
) AS q1
之后的2个表格。在下面的最后一个答案中,为了清晰起见,我在前面和后面都缩进了整个部分并留了一个空行。
然后在我的LEFT JOIN中,我通过在每个引用的开头添加 q1。来引用旧表。
以下查询完美无缺,并提供了我期望的结果。
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
(
(SELECT * 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)
) AS q1
LEFT JOIN t_object o_actparam ON
( o_actparam.name = q1.o_operation.name
AND
o_actparam.object_type = 'activityparameter'
AND
o_actparam.parentid = q1.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