Sql 根据另一个表中的值排除聚合函数中的记录

Sql 根据另一个表中的值排除聚合函数中的记录,sql,sql-server,Sql,Sql Server,我正在编写一个基于邮政编码生成统计信息的查询,并且我需要能够计算邮政编码范围内的匹配记录的数量,除非它们存在于辅助表中。这是一个更大查询的一部分,我需要每个邮政编码的记录计数以列格式显示,而不是作为单独的行显示,这个最小的示例演示了我的尝试: CREATE TABLE #People ( Name nvarchar(10), Postcode int ) INSERT INTO #People VALUES ('Adam', 2000) INSERT INTO #People

我正在编写一个基于邮政编码生成统计信息的查询,并且我需要能够计算邮政编码范围内的匹配记录的数量,除非它们存在于辅助表中。这是一个更大查询的一部分,我需要每个邮政编码的记录计数以列格式显示,而不是作为单独的行显示,这个最小的示例演示了我的尝试:

CREATE TABLE #People
(
    Name nvarchar(10),
    Postcode int
)

INSERT INTO #People VALUES ('Adam', 2000)
INSERT INTO #People VALUES ('John', 2001)
INSERT INTO #People VALUES ('Paul', 2001)
INSERT INTO #People VALUES ('Peter', 2099)
INSERT INTO #People VALUES ('Tom', 4000)

CREATE TABLE #PostcodesToIgnore
(
    Postcode int
)

INSERT INTO #PostcodesToIgnore VALUES (2099)

SELECT SUM(CASE WHEN PostCode BETWEEN 2000 AND 2099 THEN 1 ELSE 0 END) FROM #People

SELECT SUM(CASE WHEN PostCode BETWEEN 2000 AND 2099 
    AND PostCode NOT IN (SELECT PostCode FROM #PostcodesToIgnore) THEN 1 ELSE 0 END) 
    FROM #People
第一个查询统计范围内的所有邮政编码,但第二个查询失败,出现错误:

无法对包含聚合或子查询的表达式执行聚合函数


虽然我可以重构查询,将外部选择的所有条件都包含到每个子选择中,但实际查询中有很多条件,因此我希望有一种更优雅的方法来实现它?

您可以使用左连接

SELECT 
SUM
(
    CASE WHEN PostCode BETWEEN 2000 AND 2099 
        AND pcti.PostCode is null 
    THEN 1 
    ELSE 0 
    END
)
FROM #People p
left join #PostcodesToIgnore pcti on pcti.PostCode = p.PostCode

您可以使用左联接

SELECT 
SUM
(
    CASE WHEN PostCode BETWEEN 2000 AND 2099 
        AND pcti.PostCode is null 
    THEN 1 
    ELSE 0 
    END
)
FROM #People p
left join #PostcodesToIgnore pcti on pcti.PostCode = p.PostCode
您可以删除总和并将查询推送到派生表或CTE中

以下作品

SELECT SUM(PostCodeFlag)
FROM   (SELECT CASE
                 WHEN PostCode BETWEEN 2000 AND 2099
                      AND PostCode NOT IN (SELECT PostCode
                                           FROM   #PostcodesToIgnore) THEN 1
                 ELSE 0
               END AS PostCodeFlag
        FROM   #People) T 
您可以删除总和并将查询推送到派生表或CTE中

以下作品

SELECT SUM(PostCodeFlag)
FROM   (SELECT CASE
                 WHEN PostCode BETWEEN 2000 AND 2099
                      AND PostCode NOT IN (SELECT PostCode
                                           FROM   #PostcodesToIgnore) THEN 1
                 ELSE 0
               END AS PostCodeFlag
        FROM   #People) T 

来自邮政编码不在的人

事实上,看起来您根本不需要任何大小写,您可以在FROM中指定所有谓词


还是我遗漏了什么?

那些没有邮政编码的人

事实上,看起来您根本不需要任何大小写,您可以在FROM中指定所有谓词

还是我遗漏了什么?

类似这样的东西: 使用CTE预先准备数据,然后进行简单的分组计数。 或者你可以过来看看

大概是这样的: 使用CTE预先准备数据,然后进行简单的分组计数。 或者你可以过来看看


应该没有区别,应该没有区别。