来自另一个 table 的计数尚不存在,无法在 WHERE 中过滤

Counts from another table don't exist yet to filter in WHERE

我收到以下错误:

[42703] ERROR: column "nonprimarycount" does not exist 

使用此查询:

SELECT
  d.id,
  COUNT(1) FILTER (WHERE s.is_primary = True) AS primarycount,
  COUNT(1) FILTER (WHERE s.is_primary = False) AS nonprimarycount
FROM Dino d
LEFT JOIN Senator s ON d.id = s.id
WHERE nonprimarycount < 10
GROUP BY d.id
ORDER BY nonprimarycount DESC, 
            primarycount DESC;

我很清楚我不能这样做,因为我制作的 nonprimarycount 还不存在,但我不清楚如何正确地做到这一点。我想 select 仅记录少于 10 个非主要计数,我需要在查询中构建该计数。

使用 having 子句:

SELECT d.id,
       COUNT(1) FILTER (s.is_primary) AS primarycount,
       COUNT(1) FILTER (NOT s.is_primary) AS nonprimarycount
FROM Dino d LEFT JOIN
     Senator s ON d.id = s.id
GROUP BY d.id
HAVING COUNT(1) FILTER (NOT s.is_primary) < 10 
ORDER BY nonprimarycount desc, 
            primarycount desc;

我认为 Postgres 要求您重复表达式,而不是使用列别名。

你的错误是 WHERE 而不是 HAVING,就像 Gordon 指出的那样。

但我建议像这样重写您的查询:

SELECT id
     , COALESCE(s.primarycount   , 0) AS    primarycount
     , COALESCE(s.nonprimarycount, 0) AS nonprimarycount
FROM   dino d
LEFT   JOIN (
   SELECT id
        , count(*) FILTER (WHERE is_primary) AS primarycount
        , count(*) FILTER (WHERE is_primary = false) AS nonprimarycount
   FROM   senator
   GROUP  BY id
   ) s USING (id)
WHERE  (s.nonprimarycount > 9) IS NOT TRUE
ORDER  BY nonprimarycount DESC, primarycount DESC;

应该会更快。

  • 在加入之前聚合通常(快得多)。
  • 由于我们将聚合下推到子查询中,我们现在可以在外部 SELECT 中使用 WHERE 而不是 HAVING,消除错误原因。性能相同,但更简单。
  • count(*) 更快并且等效于这种情况。
  • is_primary = trueis_primary.
  • 的嘈杂说法
  • WHERE (s.nonprimarycount > 9) IS NOT TRUE 等同于 WHERE (s.nonprimarycount < 10 OR s.nonprimarycount IS NULL).
  • 我们现在可以为“table senator 中没有行”获取 NULL。我默认为 0 就像你原来的那样。如果您想改为显示差异,请删除 COALESCE 并使用 ORDER BY ... DESC NULLS LAST 对 NULL 值最后排序。
  • 值得注意的是,(不合格!)输出列名称将在 ORDER BY 中工作,即使它与外部 SELECT 中的输入列名称相同,因为 quoting the manual

If an ORDER BY expression is a simple name that matches both an output column name and an input column name, ORDER BY will interpret it as the output column name. This is the opposite of the choice that GROUP BY will make in the same situation. This inconsistency is made to be compatible with the SQL standard.

如果我们可以假设每个dinosenator中至少有一行,我们可以简化:

SELECT id
     , s.primarycount
     , s.nonprimarycount
FROM   dino d
JOIN  (
   SELECT id
        , count(*) FILTER (WHERE is_primary) AS primarycount
        , count(*) FILTER (WHERE is_primary = false) AS nonprimarycount
   FROM   senator
   GROUP  BY id
   ) s USING (id)
WHERE  s.nonprimarycount < 10
ORDER  BY s.nonprimarycount DESC, s.primarycount DESC;

现在,计数不能为 NULL。