首页 > 解决方案 > SQL - 同一张表 - 有 c2.Country <> c.Country - 需要了解

问题描述

我尝试了以下 SQL 查询,但不明白括号中的最后一部分

SELECT COUNT(c2.CustomerID) 
FROM Customers AS c2 
GROUP BY c2.Country 
HAVING c2.Country <> c.Country

作品。

SELECT COUNT(c.CustomerID) AS cnt, c.Country
FROM Customers c
GROUP BY c.Country
HAVING cnt NOT IN (SELECT COUNT(c2.CustomerID) 
                   FROM Customers AS c2 
                   GROUP BY c2.Country 
                   HAVING c2.Country <> c.Country);

前三行给了我国家名称和他们客户 ID 的数量。

例如:

Argentina 3
Belgium   3
Brazil    9
IRAN      2
Turkey    2

最后一部分

SELECT COUNT(c2.CustomerID) 
FROM Customers AS c2 
GROUP BY c2.Country 
HAVING c2.Country <> c.Country

仅返回具有相同数量的其他国家/地区的国家/地区的 count 客户 ID。这是如何运作的?

例如:

3
2

不要给巴西9分。

我不太明白 HAVING 查询的第二个条件是否有效:拥有 c2.Country <> c.Country。我知道 c2.Country <> c.Country 是什么意思。我不明白粗线是如何工作的。

当括号中的查询通过“HAVING NOT IN”链接到原始查询时,该查询实质上是比较查询第一部分的值和第二部分的值(阿根廷 3、比利时 3、伊朗 2、土耳其 2)并将返回第二个查询中不存在的所有行,即巴西 9。

标签: sql

解决方案


小提琴

鉴于:

CREATE TABLE Customers (
     CustomerID int PRIMARY KEY AUTO_INCREMENT
   , Country VARCHAR(20)
);

INSERT INTO Customers (Country) VALUES
    ('Argentina')
  , ('Argentina')
  , ('Argentina')
  , ('Belgium')
  , ('Belgium')
  , ('Belgium')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('Brazil')
  , ('IRAN')
  , ('IRAN')
  , ('Turkey')
  , ('Turkey')
;

和 SQL:

SELECT COUNT(c.CustomerID) as cnt, c.Country
  FROM Customers c
 GROUP BY c.Country
Having cnt NOT IN (SELECT COUNT(c2.CustomerID) FROM Customers AS c2 GROUP BY c2.Country Having c2.Country <> c.Country)
;

上面的 SQL 具有dependent / correlated行为,其中子查询具有对外部行 ( c.Country) 的引用。

从功能上讲,这意味着我们为外部GROUP BY子句生成的每一行执行子查询。

这也意味着我们必须小心,仅使用在功能上依赖于外部GROUP BY项的表达式来引用外部行。

首先,让我们看一下外部逻辑的整个结果GROUP BY(没有HAVING逻辑):

国家 cnt
阿根廷 3
比利时 3
巴西 9
伊朗 2
火鸡 2

让我们仅以一个外行为例:

国家 = '伊朗',cnt = 2

当我们为此行执行子查询时,我们实际上是这样做的:

(SELECT COUNT(c2.CustomerID) FROM Customers AS c2 GROUP BY c2.Country Having c2.Country <> 'IRAN')

这会生成一个列表(仅选择 cnt):

国家 cnt
阿根廷 3
比利时 3
巴西 9
火鸡 2

但是由于该HAVING条款而没有“伊朗”:Having c2.Country <> c.Country

产生的列表cnt是:3、3、9、2

现在,由于外行与 关联cnt = 2,该NOT IN子句从最终结果中消除了外行。

当我们处理这些外行时,土耳其、阿根廷和比利时也发生了同样的事情。

唯一剩下的外排是:巴西cnt = 9

如果您需要更多信息,请与我们联系。


推荐阅读