mysql - 选择不同的互斥(基于另一列的值)行

时间:2013-03-25 13:45:14

标签: mysql sql

首先,我想说,如果在阅读完这个问题之后,任何人都有关于这个问题的更多信息标题的建议,请告诉我,因为我认为我现在有点缺乏业务。

鉴于此表结构:

+---------+-------------------------------------+------+-----+---------+----------------+
| 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 |
+----+---------+------------------+----------+

我想选择所有具有' COMPLETE'所有帐户(行)的状态。

任何包含任何其他值的行的域' 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 个答案:

答案 0 :(得分:2)

这个怎么样:

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

答案 1 :(得分: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上有索引,因为这依赖于该列的连接。