我有一个这样的查询:

SELECT t1.id,
    (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) as num_things
FROM t1
WHERE num_things = 5;

目标是获取在另一个表中出现 5 次的所有元素的 id。但是,我收到此错误:

ERROR: column "num_things" does not exist
SQL state: 42703

我可能在这里做了一些愚蠢的事情,因为我对数据库有点陌生。有没有办法解决这个查询,以便我可以访问 num_things?或者,如果没有,还有其他方法可以达到这个结果吗?

有帮助吗?

解决方案

我认为您可以像这样重写您的查询:

SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) = 5;

其他提示

关于使用 SQL 的一些要点:

  • 不能在 WHERE 子句中使用列别名,但可以在 HAVING 子句中使用。这就是您收到错误的原因。
  • 与使用相关子查询相比,使用 JOIN 和 GROUP BY 可以更好地进行计数。会快很多。
  • 使用 HAVING 子句来过滤组。

这是我编写此查询的方式:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

我意识到这个查询可以跳过 JOIN 与 t1,如 Charles Bretana 的解决方案中所示。但我假设您可能希望查询包含 t1 中的一些其他列。


关于:评论中的问题:

不同之处在于 WHERE 子句在行上评估,之前 GROUP BY 将组减少为每组一行。这 HAVING 子句在组形成后进行评估。所以你不能,例如,改变 COUNT() 一个组通过使用 HAVING;您只能排除该组本身。

SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

在上面的查询中, WHERE 过滤匹配条件的行,以及 HAVING 筛选计数至少为 5 的组。

导致大多数人困惑的一点是当他们没有 GROUP BY 子句,所以它 似乎 喜欢 HAVINGWHERE 是可以互换的。

WHERE 在选择列表中的表达式之前求值。这可能并不明显,因为 SQL 语法将选择列表放在第一位。所以你可以通过使用节省大量昂贵的计算 WHERE 限制行。

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

如果您使用像上面这样的查询,则选择列表中的表达式将被计算为 每行, ,只丢弃大部分结果,因为 HAVING 健康)状况。但是,下面的查询仅计算表达式 单排 匹配的 WHERE 健康)状况。

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

回顾一下,数据库引擎根据一系列步骤运行查询:

  1. 从表中生成行集,包括由 JOIN.
  2. 评价 WHERE 针对行集的条件,过滤掉不匹配的行。
  3. 为行集中的每一行计算选择列表中的表达式。
  4. 应用列别名(请注意,这是一个单独的步骤,这意味着您不能在选择列表的表达式中使用别名)。
  5. 将组压缩为每组一行,根据 GROUP BY 条款。
  6. 评价 HAVING 针对组的条件,过滤掉不匹配的组。
  7. 对结果进行排序,根据 ORDER BY 条款。

所有其他建议都有效,但要回答你的基本问题,写

就足够了
  SELECT id  From T2
  Group By Id
  Having Count(*) = 5

我想提一下,在PostgreSQL中,没有办法在having子句中使用别名列。

SELECT usr_id AS my_id FROM user HAVING my_id = 1

不工作。

另一个不起作用的例子:

SELECT su.usr_id AS my_id,COUNT(*)AS val FROM sys_user AS su GROUP BY su.usr_id HAVING val&gt; = 1

会出现同样的错误:val列未知。

我很高兴这是因为Bill Karwin为Postgres写了一些不真实的东西:

&quot;您不能在WHERE子句中使用列别名,但您可以在HAVING子句中使用。这就是你得到错误的原因。“

试试这个

SELECT t1.id,
    (SELECT COUNT(t2.id) as myCount
     FROM t2
     WHERE t2.id = t1.id and myCount=5
          ) as num_things
FROM t1
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top