从每个 id 的 date 中获取缺少的月份

Posted

技术标签:

【中文标题】从每个 id 的 date 中获取缺少的月份【英文标题】:Get missing months from date for each and every id 【发布时间】:2019-01-05 06:36:58 【问题描述】:

我有一个包含成员 ID 和日期的表格。我想为每个成员显示从日期开始丢失的月份。

这里是输入表和期望表。

我尝试创建一个临时表来生成从最小月到最大月的系列,但我无法加入这两个表。 谁能帮我做这件事。

这是迄今为止我尝试过的代码。

提取日期并将其存储在新列中

create temp table temp_table as select *, date_part('month', premiumpadidate) from training.premium  distributed by(memberid);

生成系列

create temp table temp_table_series as 
(select * from generate_series(cast((select min(date_part) from temp_table group by (memberid)) as integer), cast((select max(date_part) from temp_table group by (memberid)) as integer) )
) 
distributed by (generate_series)

我不明白如何连接这两个表来获取每个员工的缺失月份。

请帮我做这件事

【问题讨论】:

【参考方案1】:

这很容易通过一个函数来完成,但您可以在一次选择中完成。这是我为帮助您所做的。我用联合模拟了你的数据,并添加了一个“102”成员:

select 101 as id, '2016-01-01'::date as paidDate union
select 101 as id, '2016-02-01'::date as paidDate union
select 101 as id, '2016-04-01'::date as paidDate union
select 101 as id, '2016-08-01'::date as paidDate union
select 101 as id, '2016-11-01'::date as paidDate union
select 102 as id, '2016-01-01'::date as paidDate union
select 102 as id, '2016-02-01'::date as paidDate union
select 102 as id, '2016-04-01'::date as paidDate union
select 102 as id, '2016-08-01'::date as paidDate union
select 102 as id, '2016-11-01'::date as paidDate

你应该把它当作你的桌子。

然后,我用你的表做了 12 个“案例”,以检查月份。如果找到月份,我输入“0”值,如果没有,则输入月份值,如下所示:

select t.id, extract(month from t.paidDate),
    case when extract(month from t.paidDate) = 1 then 0 else 1 end as m1,
    case when extract(month from t.paidDate) = 2 then 0 else 2 end as m2,
    case when extract(month from t.paidDate) = 3 then 0 else 3 end as m3,
    case when extract(month from t.paidDate) = 4 then 0 else 4 end as m4,
    case when extract(month from t.paidDate) = 5 then 0 else 5 end as m5,
    case when extract(month from t.paidDate) = 6 then 0 else 6 end as m6,
    case when extract(month from t.paidDate) = 7 then 0 else 7 end as m7,
    case when extract(month from t.paidDate) = 8 then 0 else 8 end as m8,
    case when extract(month from t.paidDate) = 9 then 0 else 9 end as m9,
    case when extract(month from t.paidDate) = 10 then 0 else 10 end as m10,
    case when extract(month from t.paidDate) = 11 then 0 else 11 end as m11,
    case when extract(month from t.paidDate) = 12 then 0 else 12 end as m12
from (
    select 101 as id, '2016-01-01'::date as paidDate union
    select 101 as id, '2016-02-01'::date as paidDate union
    select 101 as id, '2016-04-01'::date as paidDate union
    select 101 as id, '2016-08-01'::date as paidDate union
    select 101 as id, '2016-11-01'::date as paidDate union
    select 102 as id, '2016-01-01'::date as paidDate union
    select 102 as id, '2016-02-01'::date as paidDate union
    select 102 as id, '2016-04-01'::date as paidDate union
    select 102 as id, '2016-08-01'::date as paidDate union
    select 102 as id, '2016-11-01'::date as paidDate
) t

之后,我们需要丢弃数据中存在的月份。我使用 id 组来做到这一点,开始 MIN 月。这将丢弃存在的月份(因为我们在案例中将它们归零),并将保留不存在的月份。像这样:

select id, 
    min(m1) as m1, min(m2) as m2, min(m3) as m3, min(m4) as m4, min(m5) as m5, min(m6) as m6, 
    min(m7) as m7, min(m8) as m8, min(m9) as m9, min(m10) as m10, min(m11) as m11, min(m12) as m12
from 
(
    select t.id, extract(month from t.paidDate),
        case when extract(month from t.paidDate) = 1 then 0 else 1 end as m1,
        case when extract(month from t.paidDate) = 2 then 0 else 2 end as m2,
        case when extract(month from t.paidDate) = 3 then 0 else 3 end as m3,
        case when extract(month from t.paidDate) = 4 then 0 else 4 end as m4,
        case when extract(month from t.paidDate) = 5 then 0 else 5 end as m5,
        case when extract(month from t.paidDate) = 6 then 0 else 6 end as m6,
        case when extract(month from t.paidDate) = 7 then 0 else 7 end as m7,
        case when extract(month from t.paidDate) = 8 then 0 else 8 end as m8,
        case when extract(month from t.paidDate) = 9 then 0 else 9 end as m9,
        case when extract(month from t.paidDate) = 10 then 0 else 10 end as m10,
        case when extract(month from t.paidDate) = 11 then 0 else 11 end as m11,
        case when extract(month from t.paidDate) = 12 then 0 else 12 end as m12
    from 
    (
        select 101 as id, '2016-01-01'::date as paidDate union
        select 101 as id, '2016-02-01'::date as paidDate union
        select 101 as id, '2016-04-01'::date as paidDate union
        select 101 as id, '2016-08-01'::date as paidDate union
        select 101 as id, '2016-11-01'::date as paidDate union
        select 102 as id, '2016-01-01'::date as paidDate union
        select 102 as id, '2016-02-01'::date as paidDate union
        select 102 as id, '2016-04-01'::date as paidDate union
        select 102 as id, '2016-08-01'::date as paidDate union
        select 102 as id, '2016-11-01'::date as paidDate
    ) t
) t
group by t.id

您可以将其作为结果来执行您拥有的任何规则,但让我们通过删除零来进一步清理它,如下所示:

select id,
    case when m1 = 0 then null else m1 end, case when m2 = 0 then null else m2 end,
    case when m3 = 0 then null else m3 end, case when m4 = 0 then null else m4 end,
    case when m5 = 0 then null else m5 end, case when m6 = 0 then null else m6 end,
    case when m7 = 0 then null else m7 end, case when m8 = 0 then null else m8 end,
    case when m9 = 0 then null else m9 end, case when m10 = 0 then null else m10 end,
    case when m11 = 0 then null else m11 end, case when m12 = 0 then null else m12 end
from 
(
    select id, 
        min(m1) as m1, min(m2) as m2, min(m3) as m3, min(m4) as m4, min(m5) as m5, min(m6) as m6, 
        min(m7) as m7, min(m8) as m8, min(m9) as m9, min(m10) as m10, min(m11) as m11, min(m12) as m12
    from 
    (
        select t.id, extract(month from t.paidDate),
            case when extract(month from t.paidDate) = 1 then 0 else 1 end as m1,
            case when extract(month from t.paidDate) = 2 then 0 else 2 end as m2,
            case when extract(month from t.paidDate) = 3 then 0 else 3 end as m3,
            case when extract(month from t.paidDate) = 4 then 0 else 4 end as m4,
            case when extract(month from t.paidDate) = 5 then 0 else 5 end as m5,
            case when extract(month from t.paidDate) = 6 then 0 else 6 end as m6,
            case when extract(month from t.paidDate) = 7 then 0 else 7 end as m7,
            case when extract(month from t.paidDate) = 8 then 0 else 8 end as m8,
            case when extract(month from t.paidDate) = 9 then 0 else 9 end as m9,
            case when extract(month from t.paidDate) = 10 then 0 else 10 end as m10,
            case when extract(month from t.paidDate) = 11 then 0 else 11 end as m11,
            case when extract(month from t.paidDate) = 12 then 0 else 12 end as m12
        from 
        (
            select 101 as id, '2016-01-01'::date as paidDate union
            select 101 as id, '2016-02-01'::date as paidDate union
            select 101 as id, '2016-04-01'::date as paidDate union
            select 101 as id, '2016-08-01'::date as paidDate union
            select 101 as id, '2016-11-01'::date as paidDate union
            select 102 as id, '2016-01-01'::date as paidDate union
            select 102 as id, '2016-02-01'::date as paidDate union
            select 102 as id, '2016-04-01'::date as paidDate union
            select 102 as id, '2016-08-01'::date as paidDate union
            select 102 as id, '2016-11-01'::date as paidDate
        ) t
    ) t
    group by 
    t.id
) t

就是这样,希望对你有一点帮助。

问候

【讨论】:

以上是关于从每个 id 的 date 中获取缺少的月份的主要内容,如果未能解决你的问题,请参考以下文章

如何在mysql的列中找到缺少的月份?

不能缺少显示零的天数

Oracle:选择日期范围内缺少值的日期的值

获取数组列表中缺少的数字

访问 VBA 从月份数获取季度

表“令牌”的缺少FROM子句条目