使用带有AND,OR或NOT条件的mysql中的Count,有或没有HAVING?

时间:2014-10-01 18:51:25

标签: mysql sql database having

我的表格“用户”“作业”以及以下数据

USERS

+------+---------------+-----------+---------+---------------------+
| id   | first_name    | last_name | role_id | created             |
+------+---------------+-----------+---------+---------------------+
| 1026 | Administrator | Larvol    |       2 | 2014-07-25 22:28:21 |
|   20 | Worker        | Larvol    |       3 | 2014-07-24 20:14:18 |
|   22 | test          | user      |       3 | 2014-07-25 16:06:27 |
+------+---------------+-----------+---------+---------------------+

工作

+----+--------+---------+
| id | status | user_id |
+----+--------+---------+
|  1 |      3 |      20 |
|  2 |      4 |      22 |
+----+--------+---------+
到目前为止,我从表中获取数据的工作是

SELECT Worker.id, 
    first_name, 
    last_name, 
    role_id, 
    Worker.created, 
    (COUNT( NULLIF(Job.id, 0) )) AS  JobsAmount,
    ((SUM( IF( status <> 0, 1, 0 ) )-SUM( IF( status = 1, 1, 0 ) ))) AS  JobsReviewed 
FROM alpha_dev.users AS Worker LEFT JOIN jobs AS Job ON Job.user_id = Worker.id  
WHERE Worker.role_id = 3 
GROUP BY Worker.id;

我得到的结果是

+----+------------+-----------+---------+---------------------+------------+--------------+
| id | first_name | last_name | role_id | created             | JobsAmount | JobsReviewed |
+----+------------+-----------+---------+---------------------+------------+--------------+
| 20 | Worker     | Larvol    |       3 | 2014-07-24 20:14:18 |          1 |            1 |
| 22 | test       | user      |       3 | 2014-07-25 16:06:27 |          1 |            1 |
+----+------------+-----------+---------+---------------------+------------+--------------+

现在我想在上创建OR条件(COUNT(NULLIF(Job.id,0)))AS JobsAmount,“类似

WHERE Worker.role_id = 3 OR (COUNT( NULLIF(Job.id, 0) )) = 1

但这不起作用,所以我最终得到了HAVING子句

WHERE Worker.role_id = 3 
GROUP BY Worker.id
HAVING COUNT(NULLIF(`Job`.`id`, 0)) = 0;

HAVING在这里作为AND条件。并且给了我EMPTY SET,而我希望HAVING中的条件作为OR条件工作,所以

Worker.role_id = 3 OR COUNT(NULLIF(`Job`.`id`, 0)) = 0

应该是真的让事情完成。

任何帮助将不胜感激。谢谢

3 个答案:

答案 0 :(得分:1)

COUNT是一个聚合函数。因此,如果不对某些内容进行分组,那么它并不意味着任何事情。如果你想要那些条件的OR,那么解决方案可能是两个查询的并集,一方面查询没有,只有role_id = 3条件,另一方面查询具有COUNT条件和role_id不相等到3。

SELECT Worker.id, 
    first_name, 
    last_name, 
    role_id, 
    Worker.created, 
    (COUNT( NULLIF(Job.id, 0) )) AS  JobsAmount,
    ((SUM( IF( status <> 0, 1, 0 ) )-SUM( IF( status = 1, 1, 0 ) ))) AS  JobsReviewed 
FROM alpha_dev.users AS Worker LEFT JOIN jobs AS Job ON Job.user_id = Worker.id  
WHERE Worker.role_id = 3 
GROUP BY Worker.id

UNION

SELECT Worker.id, 
    first_name, 
    last_name, 
    role_id, 
    Worker.created, 
    (COUNT( NULLIF(Job.id, 0) )) AS  JobsAmount,
    ((SUM( IF( status <> 0, 1, 0 ) )-SUM( IF( status = 1, 1, 0 ) ))) AS  JobsReviewed 
FROM alpha_dev.users AS Worker LEFT JOIN jobs AS Job ON Job.user_id = Worker.id  
WHERE Worker.role_id <> 3 
GROUP BY Worker.id
HAVING COUNT(NULLIF(`Job`.`id`, 0)) = 0;

可能使用UNION ALL而不是UNION,它具有更好的性能,但这取决于您是否希望或因为联合而有重复的行。

答案 1 :(得分:1)

如果COUNT(NULLIF(Job.id, 0))中没有关联的行,则表达式Job将为零。

检查Job中是否存在关联行的另一种方法是查看Job中的必填列是否为空。我说必需列,因为无论如何可选列都可以为null,而如果左连接表中没有任何匹配项,则必需列将只为null。

更具体地说,在特定情况下,我非常确定COUNT(NULLIF(Job.id, 0))Job.user_id IS NULL的条件相同。由于表达式Job.user_id IS NULL不是基于聚合,因此它可以进入WHERE而不是HAVING

  • role = 3 OR job count = 0

    SELECT Worker.id, 
      first_name, 
      last_name, 
      role_id, 
      Worker.created, 
      (COUNT( NULLIF(Job.id, 0) )) AS  JobsAmount,
      ((SUM( IF( status <> 0, 1, 0 ))-SUM( IF( status = 1, 1, 0 ) ))) AS JobsReviewed 
    FROM alpha_dev.users AS Worker
    LEFT JOIN jobs AS Job ON Job.user_id = Worker.id  
    WHERE Worker.role_id = 3 OR Job.user_id IS NULL
    GROUP BY Worker.id
    

这仅适用于COUNT = 0。如果您需要检查COUNT = 2或COUNT = 5或其他什么,您需要将现有查询推送到子查询中,然后让外部查询应用OR逻辑:

  • role = 3 OR job count = 5

    SELECT * FROM (
        SELECT Worker.id, 
          first_name, 
          last_name, 
          role_id, 
          Worker.created, 
          (COUNT( NULLIF(Job.id, 0) )) AS  JobsAmount,
          ((SUM(IF(status <> 0, 1, 0))-SUM( IF(status = 1, 1, 0)))) AS JobsReviewed 
        FROM alpha_dev.users AS Worker
        LEFT JOIN jobs AS Job ON Job.user_id = Worker.id  
        GROUP BY Worker.id
    ) WorkerSummary
    WHERE role_id = 3 OR JobsAmount = 5
    

答案 2 :(得分:1)

我不知道它是否正确,但我遵循了一个技巧。而不是在where子句中写条件。我也写了条件

SELECT  Worker.id, 
        first_name,
        last_name, 
        role_id, 
        Worker.created, 
        (COUNT( NULLIF(Job.id, 0) )) AS JobsAmount, 
        ((SUM(IF(status <> 0, 1, 0))-SUM(IF(status = 1, 1, 0)))) AS JobsReviewed 
FROM alpha_dev.users AS Worker 
LEFT JOIN jobs AS Job 
ON Job.user_id = Worker.id 
GROUP BY Worker.id 
HAVING role_id = 3 OR JobsAmount = 5;

它工作得很好......所以我想问一下#34;这样构造查询是否会产生任何影响&#34;或任何性能问题??

请提供宝贵的反馈.....