7

考虑三个表 -

  users

    id      |   type
 -----------|------------
    1       |   a
    2       |   b   
    3       |   c

 types  

    id      |   type
 -----------|------------
    a       |   X
    a       |   Y   
    b       |   X
    c       |   X
    c       |   Y
    c       |   Z

 training_status

    id      |   training|   status
 -----------|-----------|-------------
    1       |   X       |   F
    2       |   X       |   S
    2       |   Y       |   S
    3       |   X       |   F
    3       |   Y       |   S

每个用户都有一个类型,类型定义了特定类型的每个用户必须完成的培训。

training_status包含用户已参加的所有培训的状态及其结果 (S,F)。如果用户尚未接受培训,则该培训不会有任何行。

我想找出所有已成功完成他们必须参加的所有培训的用户。

这是我正在考虑的方向:

select
  id
from users
  join types
    using (type)
  left join training_status
    using (id,type)
where status NOT IN(None, F);

显然这不是正确的查询,因为即使用户完成了一项培训,我们也会得到该行。在前面提到的例子中,我想得到 id = 2 因为他已经完成了这两种类型的训练。

4

4 回答 4

7

尝试

SELECT DISTINCT u.id
  FROM users u JOIN types t
    ON u.type = t.type LEFT JOIN training_status s
    ON u.id = s.id AND t.training = s.training
 WHERE s.status IS NOT NULL 
 GROUP BY u.id
HAVING COUNT(t.type) = SUM(CASE WHEN s.status = 'S' THEN 1 ELSE 0 END)

或者

SELECT DISTINCT u.id
  FROM users u JOIN types t
    ON u.type = t.type LEFT JOIN training_status s
    ON u.id = s.id AND t.training = s.training
 GROUP BY u.id
HAVING MAX(s.status IS NULL OR s.status = 'F') = 0

输出:

+------+
| 编号 |
+------+
| 2 |
+------+

这是SQLFiddle演示

于 2013-09-26T06:02:36.237 回答
0

尝试这个

SELECT *
FROM users
WHERE id NOT IN (
SELECT u.id
  FROM users u 
  JOIN types t 
    ON u.type = t.type 
  LEFT JOIN training_status s
    ON u.id = s.id AND t.training = s.training
 WHERE s.status IS NULL OR s.status = 'F')
于 2013-09-26T06:11:11.617 回答
0

尝试这个

select distinct
  u.id
from users u
  left join types t
    on u.type = t.type
  left join training_status ts
    on ts.training = t.training
where ts.status is not null
    and ts.status != 'F'
于 2013-09-26T06:12:57.027 回答
0

这应该有效:

SELECT id 
FROM users
WHERE id not in (SELECT x.id FROM (SELECT u.id AS id, t.type AS type, 'S' AS status
                FROM users u, types t
                WHERE u.type = t.id
                EXCEPT
                SELECT id, training, status
                FROM training_status
                                  ) AS x (id, type, status)
        )

请注意,它使用集合差异运算符 EXCEPT,它给出了所有可能用户的行差异及其成功的培训组合和当前的培训状态。如果所有用户的当前状态都是完整的,那么差异应该不会产生任何行。非零结果意味着有些用户没有完成所需的培训。最外层的select给出了不在未完成训练的用户列表中的用户列表,即完成的用户列表!

在 MS SQL 服务器中为您的数据执行时,它会给出答案 2,他是唯一成功完成训练的人。

这是 MySQL 版本:

SELECT id 
FROM users
WHERE id not in (SELECT x.id 
             FROM (SELECT u.id AS id, t.type AS type, 'S' AS status
                   FROM users u, types t
                   WHERE u.type = t.id 
                   ) x  
             WHERE NOT EXISTS
                    (SELECT ts.id, ts.training, ts.status
                     FROM training_status ts
                     WHERE ts.id = x.id AND 
                           ts.training = x.type AND
                           ts.status = x.status
                     )
            )

+------+
| id   |
+------+
|    2 |
+------+
1 row in set (0.00 sec)
于 2013-09-26T06:44:12.357 回答