我有一个数据集:
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
您可以生成一年的所有月份:
select add_months(date '2017-01-01', level - 1)
from dual
connect by level <= 12
您可以通过以下方式获取所有ID组合:
select distinct id1, id2, id3 from your_table
您可以交叉加入以获取所有月份的所有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,从而将其限制为仅包含指定年份中任何数据的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
...
但是更简单(效率更高,因为它只能击中你的桌子一次)。