如何合并这两个子查询?

时间:2017-10-31 15:12:12

标签: mysql sql subquery code-cleanup

我正在编写一个电子商务查询,用于轮询具有特定角色的用户。查询的确切目的并不重要,重要的是它现在按预期工作。但是,我真的想清理查询的这一部分

.
.
.
where u.firstname is not null
and u.users_id in (
  select u.users_id from users u 
  inner join mbrrole mr on mr.member_id = u.users_id and mr.ORGENTITY_ID IN (
      select ORGENTITY_ID from po_org_tree_v
  )
  inner join roledesc rd on rd.role_id = mr.role_id 
  where 1=1 
  and rd.displayname IN ('Customer Service Representative',  'Account Representative')
) 
and u.users_id in (
  select u.users_id from users u 
  inner join mbrrole mr on mr.member_id = u.users_id and mr.ORGENTITY_ID IN (
      select ORGENTITY_ID from po_org_tree_v
  )
  inner join roledesc rd on rd.role_id = mr.role_id 
  where 1=1 
  and rd.displayname = 'Registered Customer'
);

正如您所看到的,我必须在父查询的where子句中使用几乎相同的子查询,其中唯一的区别是rd.displayname检查。在sql中是否有某种方法可以将两个类似的查询同步到一个"函数"中,类似于编程语言中的实际函数?如何组合这些子查询来清理主查询?

2 个答案:

答案 0 :(得分:3)

代码正在检查每个用户可以使用两种不同类型的角色。

您当前的方法可能具有最佳性能,但您可以将其简化为一个子查询:

where u.firstname is not null and
      u.users_id in (select mr.member_id
                     from mbrrole mr inner join
                          roledesc rd
                          on rd.role_id = mr.role_id
                     where mr.ORGENTITY_ID IN (select ORGENTITY_ID from po_org_tree_v) and
                           rd.displayname IN ('Registered Customer', 'Customer Service Representative',  'Account Representative')
                     group by mr.member_id
                     having sum(rd.displayname = 'Registered Customer') > 0 and
                            sum(rd.displayname IN ('Customer Service Representative',  'Account Representative')) > 0
                    ) 

请注意以下更改:

  • 从子查询中删除了users。这不是必需的。
  • ORGENTITY_ID条件移至where子句。
  • 添加了GROUP BYHAVINGHAVING检查是否为用户定义了两种类型的角色。

答案 1 :(得分:0)

您可以使用此链接(https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html)来帮助您!

你需要使用一个过程而不是一个函数来返回一个结果集,所以这样的东西应该可以工作(MySql不是我的一杯茶):

CREATE PROCEDURE
    procedureName(s String)
BEGIN
    SELECT u.users_id 
    FROM users u 
    INNER JOIN mbrrole mr ON mr.member_id = u.users_id AND mr.ORGENTITY_ID 
    IN (
    SELECT ORGENTITY_ID FROM po_org_tree_v
    )
    INNER JOIN roledesc rd ON rd.role_id = mr.role_id 
    WHERE rd.displayname = s;
END

你可以这样称呼这个程序:

WHERE u.firstname IS NOT NULL
AND (u.users_id in procedureName('Customer Service Representative') 
     OR u.users_id in procedureName('Account Representative'))
AND u.users_id in procedureName('Registered Customer');