我有一个包含3个表的数据库。
Employee(SSN, Fname, Lname, Salary)
Project(Pnumber, Pname, Plocation)
Works_on(Essn, Pno, Hours)
我想创建一个视图,为每个项目显示其名称(Pname),有多少员工在该项目上获得超过38,000(更多)的工资,以及从事该项目的员工获得的薪酬少于38k (减)。
我的appraoch
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和项目名称。
答案 0 :(得分:3)
如果您确定要采用视图方法,这可能对您有用
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
考虑:
由于我们使用JOIN(INNER JOIN的缩写),因此不会在结果中显示没有指定员工的项目。切换到LEFT OUTER JOIN到Projects表,如果你想要显示那些以0作为值。
制作正好38k的员工也不在结果范围内。通过更改两列中的一列的case语句,随意包含它们。
如果要在不重新定义视图的情况下使该限制可自定义,您可以定义一个将限制作为参数的函数,如下所示:
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)
答案 1 :(得分:2)
使用条件SUM
代替COUNT
:
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)
请注意使用ANSI连接(您应该切换到ANSI语法)并使用>=
代替>
(否则{38}的Salary
将无法计算。< / p>
答案 2 :(得分:1)
您误解了UNION
的工作原理。 UNION
组合了数据集,它不会向其中添加精确列;它使用第一个查询中提供的别名。因此,您的列Less
将在列More
的输出中包含它的值。如果要显示列列,请尝试向两个数据集添加值为NULL
的列。另外,摆脱那些可怕的隐含的JOIN。使用JOIN
和ON
:
CREATE VIEW Compare AS
SELECT COUNT(E.SSN) as More,
NULL AS Less,
P.Pname
FROM Employee E
JOIN Project P ON W.Pno = P.Pnumber
JOIN Works_on W ON E.SSN = W.Essn
WHERE E.Salary > 38000
GROUP BY P.Pname
UNION
SELECT NULL as More,
COUNT(E.SSN) AS Less,
P.Pname
FROM Employee E
JOIN Project P ON W.Pno = P.Pnumber
JOIN Works_on W ON E.SSN = W.Essn
WHERE E.Salary < 38000
GROUP BY P.Pname;
然而,这可以简化为
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;
答案 3 :(得分:0)
首先,视图可能不适合这种情况,因为数字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
答案 4 :(得分:0)
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;