我有一个数据集:
Month id1 id2 id3 value
Jan-17 1 2 3 67
Feb-17 2 3 4 43
如何获得与一年中所有月份相对应的(id1, id2, id3)
组合?
例如。输出应该如下所示: 如果我从jan-17开始:
month id1 id2 id3 value
jan-17 1 2 3 67
feb-17 1 2 3 0
mar-17 1 2 3 0
apr-17 1 2 3 0
may-17 1 2 3 0
jun-17 1 2 3 0
jul-17 1 2 3 0
aug-17 1 2 3 0
sep-17 1 2 3 0
oct-17 1 2 3 0
nov-17 1 2 3 0
dec-17 1 2 3 0
jan-17 2 3 4 0
feb-17 2 3 4 43
mar-17 2 3 4 0
apr-17 2 3 4 0
may-17 2 3 4 0
jun-17 2 3 4 0
jul-17 2 3 4 0
aug-17 2 3 4 0
sep-17 2 3 4 0
oct-17 2 3 4 0
nov-17 2 3 4 0
dec-17 2 3 4 0
答案 0 :(得分:3)
您可以使用以下内容生成一年的所有月份:
select add_months(date '2017-01-01', level - 1)
from dual
connect by level <= 12
您可以通过以下方式获取所有ID组合:
select distinct id1, id2, id3 from your_table
您可以交叉加入thos以获取所有月份的所有ID组合:
select month, id1, id2, id3
from (
select add_months(date '2017-01-01', level - 1) as month
from dual
connect by level <= 12
)
cross join (
select distinct id1, id2, id3 from your_table
)
从您的示例数据中提供24行。然后你可以再次将 连接到你的表中以获取任何值,并在没有匹配时使用coalesce来使用零:
with cte (month, id1, id2, id3) as (
select month, id1, id2, id3
from (
select add_months(date '2017-01-01', level - 1) as month
from dual
connect by level <= 12
)
cross join (
select distinct id1, id2, id3 from your_table
)
)
select cte.month, cte.id1, cte.id2, cte.id3, coalesce(t.value, 0) as value
from cte
left join your_table t on t.month = cte.month
and t.id1 = cte.id1
and t.id2 = cte.id2
and t.id3 = cte.id3
order by cte.id1, cte.id2, cte.id3, cte.month;
MONTH ID1 ID2 ID3 VALUE
---------- ---------- ---------- ---------- ----------
2017-01-01 1 2 3 67
2017-02-01 1 2 3 0
2017-03-01 1 2 3 0
2017-04-01 1 2 3 0
2017-05-01 1 2 3 0
2017-06-01 1 2 3 0
2017-07-01 1 2 3 0
2017-08-01 1 2 3 0
2017-09-01 1 2 3 0
2017-10-01 1 2 3 0
2017-11-01 1 2 3 0
2017-12-01 1 2 3 0
2017-01-01 2 3 4 0
2017-02-01 2 3 4 43
2017-03-01 2 3 4 0
2017-04-01 2 3 4 0
2017-05-01 2 3 4 0
2017-06-01 2 3 4 0
2017-07-01 2 3 4 0
2017-08-01 2 3 4 0
2017-09-01 2 3 4 0
2017-10-01 2 3 4 0
2017-11-01 2 3 4 0
2017-12-01 2 3 4 0
如果您的ID组合仅在其他年份出现且不想要包含这些ID,则可以通过更改ID将其限制为仅包含指定年份中任何数据的ID查询以过滤:
select distinct id1, id2, id3 from your_table
where extract(year from month) = 2017
或
select distinct id1, id2, id3 from your_table
where month between date '2017-01-01' and date '2017-12-01'
我假设month
是DATE
列,其中所有值都是一个月第一天的午夜。您可以根据需要格式化显示当然。
正如@boneist所提到的,自10g以来我们可以使用partitioned outer join而不是在单独的步骤中获取这些ID:
with months (month) as (
select add_months(date '2017-01-01', level - 1)
from dual
connect by level <= 12
)
select m.month, t.id1, t.id2, t.id3, coalesce(t.value, 0) as value
from months m
left join your_table t partition by (t.id1, t.id2, t.id3)
on t.month = m.month
order by t.id1, t.id2, t.id3, m.month;
得到相同的结果:
MONTH ID1 ID2 ID3 VALUE
---------- ---------- ---------- ---------- ----------
2017-01-01 1 2 3 67
2017-02-01 1 2 3 0
2017-03-01 1 2 3 0
...
2017-01-01 2 3 4 0
2017-02-01 2 3 4 43
2017-03-01 2 3 4 0
...
但更简单(效率更高,因为它只能击中你的桌子一次)。