2013-08-28 56 views
0

考虑下表SQL连接表自行寻找差异

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存在吗? 我的头卡住了,我相信这是一个微不足道的查询,但我有这些日子之一。

+0

你如何配合他们?按ID还是按名称? –

回答

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 
) 

另外,也可以使用外部联接:基于@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 
+0

@wildplasser对不起,编辑错误 - 修复。 –

+0

谢谢大家的回答。他们都工作。由于提供了2种解决方案,因此接受了Aleks's。再次感谢。易于查询 – Thomas

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子句中的第一个条件会计算法语出现的次数。第二个是统计英语出现的次数。如果没有法文版本,并且至少有一个英文版本,则通道和名称位于结果集中。

+0

这将产生0行,因为在您的连接中,您只需要使用't2.lang ='fr''来获取行,但也需要't2.lang为null' - 就是这样必须同时'fr'和'null' –

+0

@AleksG否,问题在于那些没有'fr'行,因为我使用'left join',它将保留't1'的所有行然后过滤掉那些实际上匹配't2.lang ='fr''的内容 –

1

你可以做

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