【发布时间】:2019-09-12 17:18:23
【问题描述】:
我有两个名为 author 和 commit_metrics 的表。他们都有一个id 字段。作者有author_name 和author_email。 Commit_metrics 有author_id 和author_date。
我正在尝试编写一个查询,该查询将获取每个作者在给定一周内的提交次数,即使该数字为 0。到目前为止,这是我所拥有的:
SELECT a.id, a.author_name, a.author_email, c.week_num, COUNT(c.id)
FROM author AS a
CROSS JOIN generate_series(1, 610) AS s(n)
LEFT JOIN (SELECT c.id,
c.author_id,
c.author_date,
WEEK_NUMBER(c.author_date) AS week_num
FROM commit_metrics c) AS c ON s.n = c.week_num AND a.id = c.author_id
WHERE c.week_num IS NOT NULL
GROUP BY a.id, a.author_name, a.author_email, c.week_num
ORDER BY c.week_num DESC, a.author_name;
WEEK_NUMBER 是我为此查询编写的函数:
CREATE OR REPLACE FUNCTION WEEK_NUMBER(date TIMESTAMP) RETURNS INTEGER AS
$$
SELECT TRUNC(DATE_PART('day', date - '2008-01-01') / 7)::INTEGER;
$$ LANGUAGE SQL;
目前,该查询的工作方式类似于具有一个主要警告的魅力。当作者在给定的一周内没有提交时,它不会正确计算 0。我不确定为什么没有。当我只使用FROM 和CROSS JOIN 进行查询时,它会正确打印数千个联合作者/周。但是,当我添加 LEFT JOIN 时,它会丢失作者未提交的任何一周。
任何帮助将不胜感激。如果没有必要,我愿意取消generate_series 电话。
另外,我发现了this 的帖子,但我认为这对我的情况没有帮助。
【问题讨论】:
-
顺便说一句,您不需要创建函数来计算周数。 PostgreSQL 已经有一个功能。 stackoverflow.com/questions/34050103/…
-
了解 LEFT JOIN ON 返回的内容:INNER JOIN ON 行 UNION ALL 不匹配的左表行,由 NULL 扩展。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。 WHERE 或 INNER JOIN ON 在 OUTER JOIN ON 删除任何由 NULL 扩展的行后,需要右 [sic] 表列不为 NULL,即只留下 INNER JOIN ON 行,即“将 OUTER JOIN 转换为 INNER JOIN”。你有那个。
-
@philipxy 尽管使用 SQL 多年,但我以前从未需要过
CROSS JOIN。因为它是我使用的新东西,所以我假设我的错误比我更高级别,只是作为一个假人并使用LEFT JOIN而不是CROSS JOIN进行过滤。简单地删除WHERE子句实际上并不能解决我的问题,因为我也需要将SELECT更改为使用s.n而不是c.week_num。该链接(和您的评论)会帮助我到达那里,但这不是完全重复。你会同意/不同意吗?如果您同意,您可以取消标记我的问题吗?干杯:) -
我为一个明显的问题提供了一个欺骗链接。 (将测试从
where移动到on不是一个神奇的修复,这只是猜测而不是解释的糟糕答案。我们通常不知道修复,因为对于以where结尾的子表达式没有明确的预期规范--例如在这里。)但是由于缺少minimal reproducible example 来确定我们的第一个错误点,这篇文章仍然应该关闭(在明确之前阻止答案)可以说是“的”问题。欺骗确实适用,甚至是最深/第一个错误,我无法更改(仅放弃)近距离投票,并且在您给出 MRE 之前,有必要进行一些近距离投票。
标签: sql postgresql cross-join