我需要帮助来为下面的问题提出SQL ..我需要每月生成一行,直到我看到下一个更改
对于Ex
ID Price MMYYYY
1 $20 012016
1 $25 082016
1 $30 052017
2 $21 052016
2 $26 112016
结果数据应该是这样的
ID Price MMYYYY
1 $20 012016
1 $20 022016
1 $20 032016
1 $20 042016
1 $20 052016
1 $20 062016
1 $20 072016
1 $25 082016
1 $25 092016
1 $25 102016
1 $25 112016
1 $25 122016
1 $25 012017
1 $25 022017
1 $25 032017
1 $25 042017
1 $30 052017
2 $21 052016
2 $21 062016
2 $21 072016
2 $21 082016
2 $21 092016
2 $21 102016
2 $26 112016
基本上我有重复记录,直到我看到下一个更改..
提前致谢
答案 0 :(得分:0)
几乎可以在任何SQL数据库中使用:
一种简单的方法是使用您需要的X个月的CROSS JOIN。然后LFT将您的数据(或查询)加入该列表。 e.g。
select concat(m,y) as MMYYYY
from (
select 2016 as y union all
select 2017
) Years
cross join (
select '01' as m union all
select '02' as m union all
select '03' as m union all
select '04' as m union all
select '05' as m union all
select '06' as m union all
select '07' as m union all
select '08' as m union all
select '09' as m union all
select '10' as m union all
select '11' as m union all
select '12' as m
) Months
LEFT JOIN (
your-data-here
) d ON concat(m,y) = d.mmyyyy
只需根据需要添加/删除多年。
如果您的Hana版本支持CTE,您可以使用它"颠倒"像这样:
with Years as (
select 2016 as y union all
select 2017
)
, Months as (
select '01' as m union all
select '02' as m union all
select '03' as m union all
select '04' as m union all
select '05' as m union all
select '06' as m union all
select '07' as m union all
select '08' as m union all
select '09' as m union all
select '10' as m union all
select '11' as m union all
select '12' as m
)
select concat(m,y) as MMYYYY
from Years
cross join Months
LEFT JOIN (
your-data-here
) d ON concat(m,y) = d.mmyyyy
或者您可以使用"递归cte" (常用的表格表达式),但我认为这样做太过分了。
答案 1 :(得分:0)
以下是Used_By_Already查询的一些插件
with cte as
(
select
data.ID,
data.rn,
p.Price,
data.mmyyyy,
ifnull(p.Price,0) price2,
case when p.Price is null then 0 else 1 end as pno
from (
----------
select
*
from (
select
row_number() over (order by yyyy, mm) rn,
yyyy,
mm,
concat(mm,yyyy) mmyyyy
from (
select 2016 as yyyy from dummy
union all
select 2017 from dummy
) Years
cross join (
select '01' as mm from dummy union all
select '02' as mm from dummy union all
select '03' as mm from dummy union all
select '04' as mm from dummy union all
select '05' as mm from dummy union all
select '06' as mm from dummy union all
select '07' as mm from dummy union all
select '08' as mm from dummy union all
select '09' as mm from dummy union all
select '10' as mm from dummy union all
select '11' as mm from dummy union all
select '12' as mm from dummy
) Months
) as d
cross join (
select distinct ID from Prices
) as products
order by ID, rn
----------
) as data
left join Prices as p
on data.ID = p.ID and
data.mmyyyy = p.mmyyyy
order by data.ID, rn
)
select
ID,
rn,
mmyyyy,
max(Price) over (partition by ID, partitionno) as Price
from (
select
ID, rn, mmyyyy, Price,
( select sum(c.pno) from cte as c where c.ID = cte.ID and c.rn <= cte.rn ) as partitionno
from cte
) t
我使用SQL Row_Number() function来排序结果,并使用MAX()聚合函数和上面SQL CTE query中的partition by子句 我在SQL查询中使用了CTE表达式,就像在单个脚本块中多次查询子选择语句和临时表一样
上述SQL查询执行的部分输出如下
我希望它有所帮助
答案 2 :(得分:0)
要在接下来的几个月内复制行,直到下一个有效,请尝试:
WITH
x as (-- extract month and year in numeric format
select *, cast(substring(MMYYYY,1,2) as INTEGER) m, cast(substring(MMYYYY,3,4) as INTEGER) y
from YourTable
),
m as (-- prepare numbers 1..12 (list of monts)
select top 12 ROW_NUMBER() over (order by OBJECT_OID) m
from sys.OBJECTS
),
y as (-- expand years needed for each id
select distinct id, m.m, y
from x, m
)
-- let's do the trick
select x.ID, x.Price, right('0'+cast(y.m as varchar(2)),2)+cast(y.y as varchar(4)) MMYYYY
from y
inner join x on
-- same ID
y.ID = x.ID and (
-- match all rows from this one..
(x.y*100+x.m <= y.y*100+y.m)
and not exists (
-- until not exists a following valid row
select 1
from x xx
-- same id
where y.ID = xx.ID
-- following this one
and (xx.y*100+xx.m > x.y*100+x.m)
-- but preceding the current row
and (xx.y*100+xx.m <= y.y*100+y.m))
)
order by y.id, y.y, y.m
输出
ID Price MMYYYY
1 $20 012016
1 $20 022016
1 $20 032016
1 $20 042016
1 $20 052016
1 $20 062016
1 $20 072016
1 $25 082016
1 $25 092016
1 $25 102016
1 $25 112016
1 $25 122016
1 $25 012017
1 $25 022017
1 $25 032017
1 $25 042017
1 $30 052017
1 $30 062017
1 $30 072017
1 $30 082017
1 $30 092017
1 $30 102017
1 $30 112017
1 $30 122017
2 $21 052016
2 $21 062016
2 $21 072016
2 $21 082016
2 $21 092016
2 $21 102016
2 $26 112016
2 $26 122016