sql – 从表中的不同条件中选择COUNT

前端之家收集整理的这篇文章主要介绍了sql – 从表中的不同条件中选择COUNT前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个名为“工作”的表。对于特定用户,作业可以是活动的,存档的,逾期的,未决的或关闭的。现在每个页面请求都生成5 COUNT个查询,并尝试优化,我试图将它减少到单个查询。这是我到目前为止,但它几乎比5个单独的查询更快。请注意,我已经简化了每个子查询的条件,使其更容易理解,但是完整的查询行为相同。

有没有办法得到这5个计数在同一个查询中,而不使用低效的子查询

SELECT
  (SELECT count(*)
    FROM "jobs"
    WHERE
      jobs.creator_id = 5 AND
      jobs.status_id NOT IN (8,3,11) /* 8,11 being 'inactive' related statuses */
  ) AS active_count,(SELECT count(*)
    FROM "jobs"
    WHERE
      jobs.creator_id = 5 AND
      jobs.due_date < '2011-06-14' AND
      jobs.status_id NOT IN(8,11,5,3) /* Grabs the overdue active jobs
                                      ('5' means completed successfully) */
  ) AS overdue_count,(SELECT count(*)
    FROM "jobs"
    WHERE
      jobs.creator_id = 5 AND
      jobs.due_date BETWEEN '2011-06-14' AND '2011-06-15 06:00:00.000000'
  ) AS due_today_count

这继续有2个子查询,但我认为你得到了这个想法。

是否有更简单的方式来收集这些数据,因为基本上与作业表中相同的数据子集有5个不同的COUNT?

数据子集是“creator_id = 5”,之后每个计数基本上只有1-2个附加条件。请注意,现在我们正在使用Postgres,但可能会在不久的将来迁移到MysqL。所以如果你可以提供ANSI兼容的解决方案,我会很高兴:)

解决方法

这是典型的解决方案。使用case语句来分解不同的条件。如果一个记录满足,它会得到一个1的另一个0.然后对值进行一个SUM
SELECT
    SUM(active_count) active_count,SUM(overdue_count) overdue_count
    SUM(due_today_count) due_today_count
  FROM 
  (

  SELECT 
    CASE WHEN jobs.status_id NOT IN (8,11) THEN 1 ELSE 0 END active_count,CASE WHEN jobs.due_date < '2011-06-14' AND jobs.status_id NOT IN(8,3)  THEN 1 ELSE 0 END  overdue_count,CASE WHEN jobs.due_date BETWEEN '2011-06-14' AND '2011-06-15 06:00:00.000000' THEN 1 ELSE 0 END  due_today_count

    FROM "jobs"
    WHERE
      jobs.creator_id = 5 ) t

UPDATE
如所指出的,当0个记录返回为t时,这将导致所有值中的Null的单个结果。你有三个选择

1)Add A Having子句,使您没有返回No记录,而不是所有NULLS的结果

HAVING SUM(active_count) is not null

2)如果你希望所有的零返回,你可以添加合并到所有的总和

例如

SELECT
      COALESCE(SUM(active_count)) active_count,COALESCE(SUM(overdue_count)) overdue_count
      COALESCE(SUM(due_today_count)) due_today_count

3)利用sbarro所示的COUNT(NULL)= 0的事实。您应该注意,非空值可能是不必为1的任何东西

例如

SELECT
      COUNT(CASE WHEN 
            jobs.status_id NOT IN (8,11) THEN 'Manticores Rock' ELSE NULL
       END) as [active_count]

猜你在找的MsSQL相关文章