SQL连接表给自己找不同

时间:2013-08-28 13:38:01

标签: mysql sql join

考虑下表

CREATE TABLE `temp` (
  `id` int(11) NOT NULL,
  `lang` char(2) COLLATE utf8_unicode_ci NOT NULL,
  `channel` char(2) COLLATE utf8_unicode_ci NOT NULL,
  `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`,`lang`,`channel`)
)

insert into `temp` (`id`, `lang`, `channel`, `name`) values('1','fr','ds','Jacket');
insert into `temp` (`id`, `lang`, `channel`, `name`) values('1','en','ds','Jacket');
insert into `temp` (`id`, `lang`, `channel`, `name`) values('2','en','ds','Jeans');
insert into `temp` (`id`, `lang`, `channel`, `name`) values('3','en','ds','Sweater');
insert into `temp` (`id`, `lang`, `channel`, `name`) values('1','de','ds','Jacket');

问题是如何找到fr不存在lang en的条目? 我的头被卡住了,我相信这是一个微不足道的问题,但我现在正处于其中一天。

3 个答案:

答案 0 :(得分:1)

有几种方法可以实现这一目标。一种方法是使用带有not exists子句的子选择:

select id, channel
from temp t1
where t1.lang = 'en'
and not exists (
  select 1
  from temp t2
  where t2.lang = 'fr'
  and t1.id = t2.id
)

或者,您可以使用外部联接:

select t1.id, t1.channel
from temp t1
left outer join temp t2 on t1.id = t2.id
where t1.lang = 'en'
and t2.id is null

答案 1 :(得分:1)

基于@AleksG

SELECT t1.id, t1.channel, t1.name
FROM temp t1
LEFT JOIN temp t2 ON t1.id = t2.id AND t2.lang = 'fr'
WHERE t1.lang = 'en' AND t2.lang IS NULL 

答案 2 :(得分:1)

您可以通过聚合执行此操作:

select t.channel, t.name
from temp t
group by t.channel, t.name
having sum(case when t.lang = 'fr' then 1 else 0 end) = 0 and
       sum(case when t.lang = 'en' then 1 else 0 end) > 0;

having子句中的第一个条件会计算法语出现的次数。第二个计算英语出现的次数。如果没有法语,至少有一个用于英语,则通道和名称都在结果集中。