组合 CROSS JOIN 和 LEFT JOIN

Combine a CROSS JOIN and a LEFT JOIN

我有两个表,名为 authorcommit_metrics。他们都有一个 id 字段。作者有 author_nameauthor_email。 Commit_metrics 有 author_idauthor_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。我不确定为什么没有。当我只使用 FROMCROSS JOIN 进行查询时,它会正确打印出数千个组合 authors/weeks。但是,当我添加 LEFT JOIN 时,它会丢失作者未提交的任何一周。

如有任何帮助,我们将不胜感激。如果没有必要,我愿意取消 generate_series 调用。

此外,我发现 this post,但我认为这对我的情况没有帮助。

您的 WHERE 子句排除了 commit_metrics 上的空记录,即作者在 selected 周内没有提交的情况。您应该从 WHERE 子句中删除它以获得所需的输出。

如果您需要 WHERE 子句根据您的数据消除某些 CROSS JOIN 记录,则需要 CROSS JOINWHERE 位于sub-select 你 LEFT JOIN 到,或者在当前 WHERE 子句中创建一些更复杂的逻辑。

尽管您使用的是左连接,"WHERE c.week_num IS NOT NULL" 会过滤掉所有没有 post 的情况。试试这个:

SELECT a.id, a.author_name, a.author_email, s.n as week_num, COUNT(c.id) as post_count
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
GROUP BY a.id, a.author_name, a.author_email, s.n
ORDER BY s.n DESC, a.author_name;

去掉过滤条件。也不需要子查询,你想要 select s.n 而不是 c.week_num:

SELECT a.id, a.author_name, a.author_email, s.n as week_num, COUNT(c.id)
FROM author a CROSS JOIN
     generate_series(1, 610) AS s(n) LEFT JOIN
     commit_metrics c
     ON s.n = WEEK_NUMBER(c.author_date) AND a.id = c.author_id
GROUP BY a.id, a.author_name, a.author_email, c.week_num
ORDER BY c.week_num DESC, a.author_name;