组合 CROSS JOIN 和 LEFT JOIN
Combine a CROSS JOIN and a LEFT JOIN
我有两个表,名为 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
进行查询时,它会正确打印出数千个组合 authors/weeks。但是,当我添加 LEFT JOIN
时,它会丢失作者未提交的任何一周。
如有任何帮助,我们将不胜感激。如果没有必要,我愿意取消 generate_series
调用。
此外,我发现 this post,但我认为这对我的情况没有帮助。
您的 WHERE
子句排除了 commit_metrics
上的空记录,即作者在 selected 周内没有提交的情况。您应该从 WHERE
子句中删除它以获得所需的输出。
如果您需要 WHERE
子句根据您的数据消除某些 CROSS JOIN
记录,则需要 CROSS JOIN
和 WHERE
位于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;
我有两个表,名为 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
进行查询时,它会正确打印出数千个组合 authors/weeks。但是,当我添加 LEFT JOIN
时,它会丢失作者未提交的任何一周。
如有任何帮助,我们将不胜感激。如果没有必要,我愿意取消 generate_series
调用。
此外,我发现 this post,但我认为这对我的情况没有帮助。
您的 WHERE
子句排除了 commit_metrics
上的空记录,即作者在 selected 周内没有提交的情况。您应该从 WHERE
子句中删除它以获得所需的输出。
如果您需要 WHERE
子句根据您的数据消除某些 CROSS JOIN
记录,则需要 CROSS JOIN
和 WHERE
位于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;