You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL中用单查询返回多WHERE条件的统计结果?

合并两个差异条件的统计查询

问题描述

我有两个统计员工总数的查询,仅最后两个AND条件存在差异,希望合并为一个查询,让结果按行返回:

第一个查询(统计姓名、姓氏均不为空的员工数)

SELECT 
    COUNT(*)
FROM
(
SELECT
    E.NAME,
    E.LAST_NAME,
    E.BIRTH_DATE,
    E.ID
FROM
    EMPLOYEES E
WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
AND E.NAME IS NOT NULL 
AND E.LAST_NAME IS NOT NULL
GROUP BY E.NAME, E.LAST_NAME, E.BIRTH_DATE,E.ID
) AUX;

第二个查询(统计姓名、姓氏均为空的员工数)

SELECT 
    COUNT(*)
FROM
(
SELECT
    E.NAME,
    E.LAST_NAME,
    E.BIRTH_DATE,
    E.ID
FROM
    EMPLOYEES E
WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
AND E.NAME IS NULL 
AND E.LAST_NAME IS NULL
GROUP BY E.NAME, E.LAST_NAME, E.BIRTH_DATE,E.ID
) AUX;

预期输出

total
3
5

解决方案

方法1:直接用UNION ALL合并(逻辑直观)

完全保留原查询逻辑,通过UNION ALL将两个结果合并为两行:

SELECT COUNT(*) AS total
FROM (
    SELECT E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID
    FROM EMPLOYEES E
    WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
      AND E.NAME IS NOT NULL 
      AND E.LAST_NAME IS NOT NULL
    GROUP BY E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID
) AUX
UNION ALL
SELECT COUNT(*) AS total
FROM (
    SELECT E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID
    FROM EMPLOYEES E
    WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
      AND E.NAME IS NULL 
      AND E.LAST_NAME IS NULL
    GROUP BY E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID
) AUX;

方法2:优化分组统计(减少表扫描次数)

通过分组条件一次性统计两种情况,仅扫描一次表,效率更高:

SELECT COUNT(*) AS total
FROM (
    SELECT E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID
    FROM EMPLOYEES E
    WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
      -- 过滤出符合两种条件的记录
      AND ((E.NAME IS NOT NULL AND E.LAST_NAME IS NOT NULL) OR (E.NAME IS NULL AND E.LAST_NAME IS NULL))
    GROUP BY E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID,
             -- 按条件分组,区分两种统计情况
             CASE WHEN E.NAME IS NOT NULL AND E.LAST_NAME IS NOT NULL THEN 1 ELSE 2 END
) AUX
GROUP BY CASE WHEN E.NAME IS NOT NULL AND E.LAST_NAME IS NOT NULL THEN 1 ELSE 2 END;

如果不需要保留原查询的子查询结构,还可以简化为:

SELECT COUNT(DISTINCT CONCAT(E.NAME, E.LAST_NAME, E.BIRTH_DATE, E.ID)) AS total
FROM EMPLOYEES E
WHERE E.BIRTH_DATE BETWEEN '2022-10-18 00:00:00' AND '2022-10-18 23:59:59'
  AND ((E.NAME IS NOT NULL AND E.LAST_NAME IS NOT NULL) OR (E.NAME IS NULL AND E.LAST_NAME IS NULL))
GROUP BY CASE 
           WHEN E.NAME IS NOT NULL AND E.LAST_NAME IS NOT NULL THEN 1 
           ELSE 2 
         END;

内容的提问来源于stack exchange,提问作者Mikasa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:55:23