Select 并为没有任何数据的行分配 0
Select and assign 0 for the rows which does not have any data
我们有客户要求,如果对于特定条件,没有可用数据,则在从数据库中选择列时分配 0。
下面是table结构。我们需要从今天提取过去 6 个月的数据,其中性别为 'M'。如果某个月没有 'Male'/'Female'(根据 where 条件)参与者,则显示该月有 0 个参与者。
yearMonth participants gender
202101 1 F
202102 0 M
202103 0 F
202003 0 M
202104 0 F
202105 0 F
202105 30 F
202105 5 M
202106 22 F
202106 20 M
202107 14 F
202108 29 M
没有任何 where 条件,查询如下所示 -
select yearMonth, sum(participants) as participants
from table_name
where yearMonth
between 202104 and 202108 group by yearMonth;
这个查询 returns -
yearMonth participants
202103 0
202104 0
202105 35
202106 42
202107 14
202108 29
当我们添加 where 条件时 -
select yearMonth, sum(participants) as participants
from table_name
where yearMonth
between 202104 and 202108
where gender = 'M' group by yearMonth;
它returns
yearMonth participants
202105 5
202106 20
202107 14
202108 29
但要求是,还要return202103和202104,其中0为参与者。
yearMonth participants
202103 0
202104 0
202105 5
202106 20
202107 14
202108 29
我们可以使用 Postgre SQL 来完成吗?如果可以,请帮助我。
使用日历table方法:
WITH dates AS (
SELECT CAST('2021-01-01' AS DATE) + (n || ' month')::INTERVAL dt
FROM generate_series(0, 11) n
)
SELECT
TO_CHAR(d.dt, 'YYYYMM')::int AS yearMonth,
SUM(t.participants) FILTER (WHERE t.gender = 'M') AS male_participants
FROM dates d
LEFT JOIN table_name t
ON t.yearMonth = d.yearMonth
WHERE
TO_CHAR(d.dt, 'YYYYMM')::int BETWEEN 202101 AND 202108 AND
GROUP BY
TO_CHAR(d.dt, 'YYYYMM')::int;
您可以使用条件聚合
select yearMonth, sum(case when gender = 'M' then participants else 0 end) as participants
from table_name
where yearMonth
between 202104 and 202108
group by yearMonth;
仅当今年月份的原始 table 中根本没有任何参与者 raw 时,才会缺少 yearMonth raw。
一种方法是条件聚合,在 Postgres 中看起来像这样:
select yearMonth,
sum(participants) filter (where gender = 'M') as male_participants
from table_name
where yearMonth between 202104 and 202108
group by yearMonth;
但是,您的条件是:
We need to pull last 6 months data from today where gender is 'M'.
为此,我建议 generate_series()
以便自动进行日期比较:
select v.yearMonth,
coalesce(sum(participants), 0) as male_participants
from generate_series(0, 5, 1) gs(n) cross join lateral
(values (to_char(date_trunc(month, current_date) - gs.n * interval '1 month', 'YYYYMM')::int)
) v(yearMonth) left join
table_name t
on t.yearMonth = v.yearMonth::int and
t.gender = 'M'
group by v.yearMonth
order by v.yearmonth;
我们有客户要求,如果对于特定条件,没有可用数据,则在从数据库中选择列时分配 0。
下面是table结构。我们需要从今天提取过去 6 个月的数据,其中性别为 'M'。如果某个月没有 'Male'/'Female'(根据 where 条件)参与者,则显示该月有 0 个参与者。
yearMonth participants gender
202101 1 F
202102 0 M
202103 0 F
202003 0 M
202104 0 F
202105 0 F
202105 30 F
202105 5 M
202106 22 F
202106 20 M
202107 14 F
202108 29 M
没有任何 where 条件,查询如下所示 -
select yearMonth, sum(participants) as participants
from table_name
where yearMonth
between 202104 and 202108 group by yearMonth;
这个查询 returns -
yearMonth participants
202103 0
202104 0
202105 35
202106 42
202107 14
202108 29
当我们添加 where 条件时 -
select yearMonth, sum(participants) as participants
from table_name
where yearMonth
between 202104 and 202108
where gender = 'M' group by yearMonth;
它returns
yearMonth participants
202105 5
202106 20
202107 14
202108 29
但要求是,还要return202103和202104,其中0为参与者。
yearMonth participants
202103 0
202104 0
202105 5
202106 20
202107 14
202108 29
我们可以使用 Postgre SQL 来完成吗?如果可以,请帮助我。
使用日历table方法:
WITH dates AS (
SELECT CAST('2021-01-01' AS DATE) + (n || ' month')::INTERVAL dt
FROM generate_series(0, 11) n
)
SELECT
TO_CHAR(d.dt, 'YYYYMM')::int AS yearMonth,
SUM(t.participants) FILTER (WHERE t.gender = 'M') AS male_participants
FROM dates d
LEFT JOIN table_name t
ON t.yearMonth = d.yearMonth
WHERE
TO_CHAR(d.dt, 'YYYYMM')::int BETWEEN 202101 AND 202108 AND
GROUP BY
TO_CHAR(d.dt, 'YYYYMM')::int;
您可以使用条件聚合
select yearMonth, sum(case when gender = 'M' then participants else 0 end) as participants
from table_name
where yearMonth
between 202104 and 202108
group by yearMonth;
仅当今年月份的原始 table 中根本没有任何参与者 raw 时,才会缺少 yearMonth raw。
一种方法是条件聚合,在 Postgres 中看起来像这样:
select yearMonth,
sum(participants) filter (where gender = 'M') as male_participants
from table_name
where yearMonth between 202104 and 202108
group by yearMonth;
但是,您的条件是:
We need to pull last 6 months data from today where gender is 'M'.
为此,我建议 generate_series()
以便自动进行日期比较:
select v.yearMonth,
coalesce(sum(participants), 0) as male_participants
from generate_series(0, 5, 1) gs(n) cross join lateral
(values (to_char(date_trunc(month, current_date) - gs.n * interval '1 month', 'YYYYMM')::int)
) v(yearMonth) left join
table_name t
on t.yearMonth = v.yearMonth::int and
t.gender = 'M'
group by v.yearMonth
order by v.yearmonth;