我的下表有两个字段,即a和b,如下所示:
[X,Y] = meshgrid(-8:0.5:8);
R = sqrt(X.^2+Y.^2)+eps;
Z = sin(R)./R;
for i = 1 : 4
cmd = horzcat('figure_in_',num2str(i),' = surf(X,Y,Z)'); eval(cmd);
if exist('fig_container.mat','file')
save('fig_container.mat',horzcat('figure_in_',num2str(i)),'-append');
else
save('fig_container.mat',horzcat('figure_in_',num2str(i)));
end
end
clearvars -except fig_container
close all
插入一些记录:
create table employe
(
empID varchar(10),
department varchar(10)
);
insert into employe values('A101','Z'),('A101','X'),('A101','Y'),('A102','Z'),('A102','X'),
('A103','Z'),('A103','Y'),('A104','X'),('A104','Y'),('A105','Z'),('A106','X');
select * from employe;
注意:现在,我想显示仅属于且仅属于部门empID department
------------------
A101 Z
A101 X
A101 Y
A102 Z
A102 X
A103 Z
A103 Y
A104 X
A104 Y
A105 Z
A106 X
和Z
的员工。
因此,根据条件,应该显示唯一的员工Y
,因为他只属于
部门A103
和Z
。但是员工Y
不应该出现,因为他属于A101
。
预期结果:
如果条件为:Z,X, and Y
和Z
,则结果应为:
Y
如果条件为:empID
------
A103
和Z
,则结果应为:
X
如果条件为:empID
------
A102
,Z
和X
,则结果应为:
Y
注意:我只想在empID
------
A101
子句中执行此操作(不想使用where
和group by
子句) ,因为我将把这个包含在另一个having
中。
答案 0 :(得分:24)
这是 关系部门,没有剩余(RDNR) 问题。请参阅Dwain Camps的article,为这类问题提供了许多解决方案。
第一个解决方案
SELECT empId
FROM (
SELECT
empID, cc = COUNT(DISTINCT department)
FROM employe
WHERE department IN('Y', 'Z')
GROUP BY empID
)t
WHERE
t.cc = 2
AND t.cc = (
SELECT COUNT(*)
FROM employe
WHERE empID = t.empID
)
第二个解决方案
SELECT e.empId
FROM employe e
WHERE e.department IN('Y', 'Z')
GROUP BY e.empID
HAVING
COUNT(e.department) = 2
AND COUNT(e.department) = (SELECT COUNT(*) FROM employe WHERE empID = e.empId)
不使用GROUP BY
和HAVING
:
SELECT DISTINCT e.empID
FROM employe e
WHERE
EXISTS(
SELECT 1 FROM employe WHERE department = 'Z' AND empID = e.empID
)
AND EXISTS(
SELECT 1 FROM employe WHERE department = 'Y' AND empID = e.empID
)
AND NOT EXISTS(
SELECT 1 FROM employe WHERE department NOT IN('Y', 'Z') AND empID = e.empID
)
答案 1 :(得分:7)
我知道这个问题已经得到了回答,但这是一个有趣的问题,我尝试以别人没有的方式做到这一点。我的好处是你可以输入任何字符串列表,只要每个值后面都有一个逗号,你不必担心检查计数。
注意:值必须按字母顺序列出。
select DISTINCT empID
FROM employe A
CROSS APPLY
(
SELECT department + ','
FROM employe B
WHERE A.empID = B.empID
ORDER BY department
FOR XML PATH ('')
) CA(Deps)
WHERE deps = 'Y,Z,'
<强>结果:强>
empID
----------
A103
答案 2 :(得分:6)
条件1:z和y
select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'y' ) as y
on z.empID = y.empID
where z.empID Not in(select empID from employe where department = 'x' )
条件1:z和x
select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'x' ) as x
on z.empID = x.empID
where z.empID Not in(select empID from employe where department = 'y' )
条件1:z,y和x
select z.empID from (select empID from employe where department = 'z' ) as z
inner join (select empID from employe where department = 'x' ) as x
on z.empID = x.empID
inner join (select empID from employe where department = 'y' ) as y on
y.empID=Z.empID
答案 3 :(得分:5)
您可以GROUP BY
使用having
。 SQL Fiddle
SELECT empID
FROM employe
GROUP BY empID
HAVING SUM(CASE WHEN department= 'Y' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department= 'Z' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department NOT IN('Y','Z') THEN 1 ELSE 0 END) = 0
没有GROUP BY
和Having
SELECT empID
FROM employe E1
WHERE (SELECT COUNT(DISTINCT department) FROM employe E2 WHERE E2.empid = E1.empid and department IN ('Z','Y')) = 2
EXCEPT
SELECT empID
FROM employe
WHERE department NOT IN ('Z','Y')
如果要使用连接使用上述任何查询与其他表,您可以使用CTE或这样的派生表。
;WITH CTE AS
(
SELECT empID
FROM employe
GROUP BY empID
HAVING SUM(CASE WHEN department= 'Y' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department= 'Z' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN department NOT IN('Y','Z') THEN 1 ELSE 0 END) = 0
)
SELECT cols from CTE join othertable on col_cte = col_othertable
答案 4 :(得分:4)
试试这个
select empID from employe
where empId in (select empId from employe
where department = 'Z' and department = 'Y')
and empId not in (select empId from employe
where department = 'X') ;
答案 5 :(得分:4)
对于If条件是:Z和Y
SELECT EMPID FROM EMPLOYE WHERE DEPARTMENT='Z' AND
EMPID IN (SELECT EMPID FROM EMPLOYE WHERE DEPARTMENT ='Y')AND
EMPID NOT IN(SELECT EMPID FROM EMPLOYE WHERE DEPARTMENT NOT IN ('Z','Y'))
答案 6 :(得分:3)
以下查询适用于您希望来自部门&#39; Y&#39;和&#39; Z&#39;而不是&#39; X&#39;。
select empId from employe
where empId in (select empId from employe
where department = 'Z')
and empId in (select empId from employe
where department = 'Y')
and empId not in (select empId from employe
where department = 'X') ;
对于第二种情况,只需在最后一个条件中将not in
替换为in
。
答案 7 :(得分:3)
试试这个,
SELECT a.empId
FROM employe a
INNER JOIN
(
SELECT empId
FROM employe
WHERE department IN ('X', 'Y', 'Z')
GROUP BY empId
HAVING COUNT(*) = 3
)b ON a.empId = b.empId
GROUP BY a.empId
计数必须基于条件数量。
答案 8 :(得分:1)
您也可以使用GROUP BY
和HAVING
- 您只需要在子查询中执行此操作。
例如,让我们从一个简单的查询开始,找到部门 X 和 Y (而不是任何其他部门)的所有员工:
SELECT empID,
GROUP_CONCAT(DISTINCT department ORDER BY department ASC) AS depts
FROM emp_dept GROUP BY empID
HAVING depts = 'X,Y'
我在这里使用MySQL的GROUP_CONCAT()
功能作为一种方便的快捷方式,但如果没有它,你也可以获得相同的结果,例如像这样:
SELECT empID,
COUNT(DISTINCT department) AS all_depts,
COUNT(DISTINCT CASE
WHEN department IN ('X', 'Y') THEN department ELSE NULL
END) AS wanted_depts
FROM emp_dept GROUP BY empID
HAVING all_depts = wanted_depts AND wanted_depts = 2
现在,要将此与其他查询条件相结合,只需执行包含其他条件的查询,然后根据上述查询的输出加入您的employees表:
SELECT empID, name, depts
FROM employees
JOIN (
SELECT empID,
GROUP_CONCAT(DISTINCT department ORDER BY department ASC) AS depts
FROM emp_dept GROUP BY empID
HAVING depts = 'X,Y'
) AS tmp USING (empID)
WHERE -- ...add other conditions here...
Here's an SQLFiddle demonstrating this query.
聚苯乙烯。您应该使用JOIN
代替IN
子查询的原因是因为MySQL is not so good at optimizing IN
subqueries.
具体来说(至少从v5.7开始),MySQL总是将IN
子查询转换为依赖子查询,因此必须为外部的每一行重新执行子查询查询,即使原始子查询是独立的。例如,以下查询(来自上面链接的文档):
SELECT ... FROM t1 WHERE t1.a IN (SELECT b FROM t2);
有效地转换为:
SELECT ... FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t1.a);
如果t2
很小和/或索引允许快速查找,可能仍然相当快。但是,如果(如上面的原始示例中)执行子查询可能需要大量工作,性能可能会受到严重影响。使用JOIN
代替只允许子查询执行一次,因此通常可以提供更好的性能。
答案 9 :(得分:1)
自我加入怎么样? (符合ANSI标准 - 工作20年以上)
SELECT * FROM employee e JOIN employee e2 ON e.empid = e2.empid
WHERE e.department = 'x' AND e2.department ='y'
这表明a101和a104都适用于两个部门。
答案 10 :(得分:1)
使用where
子句的解决方案:
select distinct e.empID
from employe e
where exists( select *
from employe
where empID = e.empID
having count(department) = count(case when department in('Y','X','Z') then department end)
and count(distinct department) = 3)
exists
检查是否有特定EmpId
的记录,其总计数department
s等于仅匹配department
s的条件计数,并且它也相等到department
子句提供的in
个数。另外值得一提的是,我们在整个集合中应用having
子句而没有group by
子句,但已经指定,只有一个empID
。
您可以在没有相关子查询的情况下实现此目的,但使用group by
子句:
select e.empId
from employe e
group by e.empID
having count(department) = count(case when department in('Y','X','Z') then department end)
and count(distinct department) = 3
您还可以为上述查询使用having
子句的其他变体:
having count(case when department not in('Y','X', 'Z') then department end) = 0
and count(distinct case when department in('Y','X','Z') then department end) = 3
答案 11 :(得分:1)
在Postgres中,可以使用数组简化:
{
"autogenerated": true,
"release": "2017.xx.xx.xxxx",
"content_url": "http://xxxxxxxx/hotcodeDir",
"update": "now",
对http://xxxxxxxx/hotcodeDir/
中的元素进行排序并将它们按照相同顺序与排序的部门列表进行比较非常重要。否则,这将不会返回正确的答案。
E.g。 select empid
from employee
group by empid
having array_agg(department order by department)::text[] = array['Y','Z'];
可能会返回错误的结果。
这可以使用CTE以更灵活的方式为部门提供:
array_agg()
这样,元素的排序总是由数据库完成,并且在聚合数组中的值与比较它的值之间是一致的。
标准SQL的一个选项是检查至少有一行是否具有不同的部门以及计算所有行
array_agg(department) = array['Z', 'Y']
如果单个员工可能被分配到同一个部门,上述解决方案将无效!
使用汇总with depts_to_check (dept) as (
values ('Z'), ('Y')
)
select empid
from employee
group by empid
having array_agg(department order by department) = array(select dept from depts_to_check order by dept);
可以在Postgres中简化select empid
from employee
group by empid
having min(case when department in ('Y','Z') then 1 else 0 end) = 1
and count(case when department in ('Y','Z') then 1 end) = 2;
。
当应用标准having min (...)
条件来进行条件聚合时,也可以使用可以将员工分配到同一部门两次的情况
bool_and()
filter()
仅在组中所有行的条件为真时才返回true。
标准SQL的另一个解决方案是使用至少包含这两个部门的员工与分配给两个部门的员工之间的交集:
select empid
from employee
group by empid
having bool_and(department in ('Y','Z'))
and count(distinct department) filter (where department in ('Y','Z')) = 2;