sql join and minus

时间:2016-04-21 22:44:52

标签: sql oracle

I seem to be having problem getting a certain query to work. I know I'm so close. Here's a copy of my er diagram

I think I am so close to achieving what I want to do with this code, only I get invalid identifier when trying to run it. I think its because the practice is being changed somehow after joining, as I am only getting invalid identifier on row 5?

SELECT   staffid, staff_firstname, staff_surname, practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
MINUS
SELECT   staffid, staff_firstname, staff_surname, practice.practice_name, practice.practice_city
from staff
where    role = 'GP';

Basically I'm trying to use the minus construct to find practices which do not employ a GP and include some information such as the CITY and practice_address.

I can use the minus construct to find out how many staff do not have the role of GP like so:

SELECT   staffid, staff_firstname, staff_surname
from staff
MINUS
SELECT   staffid, staff_firstname, staff_surname
from staff
where    role = 'GP';

where I get the results:

   STAFFID STAFF_FIRS STAFF_SURN
__________ __________ __________
         8 NYSSA      THORNTON
         9 MONA       BRADSHAW
        10 GLORIA     PENA

I'm struggling to use the join with the minus construct to get information about the GP's practice address and city etc.

Any help would be greatly appreciated!

2 个答案:

答案 0 :(得分:2)

第二个选择,在减号之后,是指练习表中的列 - 但它不会加入它:

SELECT staffid, staff_firstname, staff_surname,
  practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
MINUS
SELECT staffid, staff_firstname, staff_surname,
  practice.practice_name, practice.practice_city
from staff
join practice on staff.practiceid = practice.practiceid
where    role = 'GP';

这不会给你你想要的东西,它只会删除GP的工作人员的行,而不是所有有GP的实践的痕迹 - 所有实践中的非GP员工仍将显示。

如果您不想要剩余的员工详细信息,您只需要在选择列表中包含练习表中的列,然后减号就可以提供您想要的内容(而且Gordon Linoff已经显示了两个{{{ 1}}在那种情况下)。如果您确实需要剩余的员工详细信息,那么您可以使用not-exists子句而不是minus - 类似于:

minus

这与Gordon的第二个查询类似,但有一个额外的联接select s.staffid, s.staff_firstname, s.staff_surname, p.practice_name, p.practice_city from staff s join practice p on s.practiceid = p.practiceid where not exists ( select 1 from staff s2 where s2.practice_id = p.practice_id and s2.role = 'GP ); 以获取详细信息。同样,如果你不想要那些,请使用Gordon更简单的查询。

你也可以使用聚合检查,或者如果你已经学习了那些,可以用分析函数做一些事情,以节省必须两次击中表。

答案 1 :(得分:1)

您的原始查询仅在“职员”级别上运行,而不是“练习”级别。我倾向于使用聚合来解决这个问题:

select  p.practice_name, p.practice_city
from staff s join
     practice p
     on s.practiceid = p.practiceid
group by p.practice_name, p.practice_city
having sum(case when s.role = 'GP' then 1 else 0 end) = 0;

或者,甚至更好:

select p.*
from practice p
where not exists (select 1
                  from staff s
                  where s.practiceid = p.practiceid and s.role = 'GP'
                 );

我认为这是对您问题的最简单和最直接的解释。