2013-03-25 103 views
2

首先,我想说,如果在阅读完问题之后,任何人都有关于此问题的更多信息标题的建议,请告诉我我认为我是有所欠缺,目前,企业...mysql - 选择不同的互斥(基于另一列的值)行

鉴于这种表结构:

+---------+-------------------------------------+------+-----+---------+----------------+ 
| Field | Type        | Null | Key | Default | Extra   | 
+---------+-------------------------------------+------+-----+---------+----------------+ 
| id  | int(11)        | NO | PRI | NULL | auto_increment | 
| account | varchar(20)       | YES | UNI | NULL |    | 
| domain | varchar(100)      | YES |  | NULL |    | 
| status | enum('FAILED','PENDING','COMPLETE') | YES |  | NULL |    | 
+---------+-------------------------------------+------+-----+---------+----------------+ 

而这个数据:

+----+---------+------------------+----------+ 
| id | account | domain   | status | 
+----+---------+------------------+----------+ 
| 1 | jim  | somedomain.com | COMPLETE | 
| 2 | bob  | somedomain.com | COMPLETE | 
| 3 | joe  | somedomain.com | COMPLETE | 
| 4 | frank | otherdomain.com | COMPLETE | 
| 5 | betty | otherdomain.com | PENDING | 
| 6 | shirley | otherdomain.com | FAILED | 
| 7 | tom  | thirddomain.com | FAILED | 
| 8 | lou  | fourthdomain.com | COMPLETE | 
+----+---------+------------------+----------+ 

我想选择素t所有帐户(行)都具有“完成”状态的所有域。

任何具有包含状态'COMPLETE'的任何值的行的域都不能返回。

所以在上面的例子中,我预期的结果将是:

+------------------+ 
| domain   | 
+------------------+ 
| somedomain.com | 
| fourthdomain.com | 
+------------------+ 

很显然,我可以做到这一点通过使用子查询,如:

mysql> select distinct domain from test_table where status = 'complete' and domain not in (select distinct domain from test_table where status != 'complete'); 
+------------------+ 
| domain   | 
+------------------+ 
| somedomain.com | 
| fourthdomain.com | 
+------------------+ 
2 rows in set (0.00 sec) 

这将工作罚款我们的小型模拟测试表,但在实际情况下,所讨论的表格将是数十(甚至数百)万行,并且我很好奇,是否有一些更有效的方式来做到这一点,例如子查询是缓慢和密集的。

回答

2

如何:

select domain 
from test_table 
group by domain 
having sum(case when status = 'COMPLETE' 
       then 0 else 1 end) = 0 
+0

非常好!这正是我所需要的。 – 2013-03-25 13:59:35

+0

请在你的回答中看到我的评论。 – 2013-03-25 14:08:33

+0

+1显然执行v。,并且很甜/很容易启动。好一个。 – Sepster 2013-03-25 14:13:40

0

我认为这会工作。有效地将两个基本查询结合在一起,然后比较它们的计数。

select 
    main.domain 
from 
    your_table main 

    inner join 
    (
     select 
      domain, count(id) as cnt 
     from 
      your_table 
     where 
      status = 'complete' 
     group by 
      domain 
    ) complete 
    on complete.domain = main.domain 

group by 
    main.domain 

having 
    count(main.id) = complete.cnt 

您还应该确保您在domain有一个索引作为这依赖于该列有加入。

+0

虽然这种方法确实执行得更好,但是我选择了其他答案,因为它比这个更好。在具有10k行的表格上,您的查询在5.56秒内执行操作,另一个答案为0.11。 – 2013-03-25 14:08:08

+0

@jesse_galley对不起,这个错误是用手写在文本编辑器中的。公平的性能,看起来像mySql必须非常快速地在最终结果中的每一行上执行'case'...或者做一些聪明的优化。我实际上已经简化了它,所以不知道是否有兴趣再次检查它。不知道它会更快,但可能值得快速检查。但肯定无法与甜美简单的其他答案相匹配!祝你好运。顺便提一下,问题的+1。好的问。 – Sepster 2013-03-25 14:12:37

相关问题