Sql 同一视图上具有不同条件的两个计数查询

Sql 同一视图上具有不同条件的两个计数查询,sql,sql-server,Sql,Sql Server,我有一个包含3个表的数据库 Employee(SSN, Fname, Lname, Salary) Project(Pnumber, Pname, Plocation) Works_on(Essn, Pno, Hours) 我想创建一个视图,显示每个项目的名称Pname,有多少在该项目上工作的员工获得的工资高于38k,有多少在该项目上工作的员工获得的工资低于38k 我的预约 create view compare as ( (select count(E.SSN

我有一个包含3个表的数据库

Employee(SSN, Fname, Lname, Salary)
Project(Pnumber, Pname, Plocation)
Works_on(Essn, Pno, Hours)
我想创建一个视图,显示每个项目的名称Pname,有多少在该项目上工作的员工获得的工资高于38k,有多少在该项目上工作的员工获得的工资低于38k

我的预约

    create view compare as 
    (
       (select count(E.SSN) as More, P.Pname
        from Employee as E, Project as P, Works_on as W
        where E.Salary > 38000 and W.Pno = P.Pnumber and E.SSN = W.Essn 
        group by(P.Pname)) union 

       (select count(E.SSN) as Less, P.Pname
        from Employee as E, Project as P, Works_on as W
        where E.Salary < 38000 and W.Pno = P.Pnumber and E.SSN = W.Essn 
        group by(P.Pname))
    );

但它只显示了更多的col和项目名称

首先,视图可能不适合这种情况,因为38000可能会随着时间的推移而改变

其次,案例结构似乎适合这种情况。总的想法是:

select case when salary >= 38000 then 'more' else 'less' end salaryRange
, count(*) employees
etc
group by case when salary >= 38000 then 'more' else 'less' end

你误解了工会的运作方式。UNION组合数据集,它不向其中添加精确的列;它使用第一个查询中提供的别名。因此,列Less的值将出现在列More的输出中。如果希望显示列,请尝试向两个数据集中添加一个值为NULL的列。另外,要摆脱那些可怕的隐式连接。使用“连接”和“打开”:

然而,这可以简化为

CREATE VIEW Compare AS

      SELECT CASE WHEN E.Salary > 38000 THEN COUNT(E.SSN) END AS More,
             CASE WHEN E.Salary < 38000 THEN COUNT(E.SSN) END AS Less,
             P.Pname
      FROM Employee E
           JOIN Project P ON W.Pno = P.Pnumber
           JOIN Works_on W ON E.SSN = W.Essn 
      GROUP BY P.Pname;

如果您确定要使用视图方法,那么这可能适合您

select p.Pname
, sum(case when e.Salary < 38000 then 1 else 0 end) as under_38_k
, sum(case when e.Salary > 38000 then 1 else 0 end) as over_38_k
from Works_on w
join Employee e on e.ssn = w.essn
join Project p on p.Pnumber = w.Pno
group by p.Pname
order by p.Pname asc --customize as needed
使用条件和代替计数:


注意ANSI连接的使用您应该切换到ANSI语法并使用>=代替>,否则将不计算38000的工资。

您实际上不需要工会。一个简单的案例就可以了。是的,很快就意识到了这一点,并且在你发表评论时已经在研究解决方案了。谢谢:我的投票使你的声誉超过50。你欠我一杯啤酒,现在你可以评论别人的帖子了。@DanBracuk你每次访问乌拉圭都会说出时间和地点;谢谢你的投票!谢谢。我还有一个问题,如果我想添加一个属性,即两个和之间的差,该怎么办。我该怎么做?再次感谢。@sayedalesaw最快的方法是:用括起来,然后选择两列加上一列,这是两者的区别。例如:选择More,Less,More-Less diff,Pname from…@SayedAlesawy刚刚编辑添加列,这只是上面相同总和的减法。如果需要,请更改这些术语的顺序。COUNT是错误的,因为它不考虑所有行。你需要使用SUM@tonypdmtr哎呀,我说在文本中使用SUM,但是复制粘贴计数。
create view compare as
  select sum(case when Salary >= 38000 then 1 else 0 end) as More,
         sum(case when Salary <  38000 then 1 else 0 end) as Less,
         sum(case when Salary >= 38000 then 1 else -1 end) as Diff,
         Pname
    from Project join Works_on on Pno = Pnumber
    join Employee on SSN = Essn
    group by Pname;
CREATE FUNCTION EmployeesEarnings(@limit int)  
RETURNS TABLE  
AS  
RETURN  
select p.Pname
, sum(case when e.Salary < @limit then 1 else 0 end) as under_limit
, sum(case when e.Salary > @limit then 1 else 0 end) as over_limit
, sum(case when e.Salary < @limit then 1 else 0 end) - sum(case when e.Salary > @limit then 1 else 0 end) as difference
from Works_on w
join Employee e on e.ssn = w.essn
join Project p on p.Pnumber = w.Pno
group by p.Pname
select *
from EmployeesEarnings(38000)
select
    SUM(CASE WHEN E.Salary >= 38000 THEN 1 ELSE 0 END) as More
,   SUM(CASE WHEN E.Salary < 38000 THEN 1 ELSE 0 END) as Less
,   P.Pname
from Employee as E
join Works_on as W ON E.SSN = W.Essn 
join Project as P ON W.Pno = P.Pnumber
group by(P.Pname)
create view compare as
  select sum(case when Salary >= 38000 then 1 else 0 end) as More,
         sum(case when Salary <  38000 then 1 else 0 end) as Less,
         sum(case when Salary >= 38000 then 1 else -1 end) as Diff,
         Pname
    from Project join Works_on on Pno = Pnumber
    join Employee on SSN = Essn
    group by Pname;