我为一家公司工作,该公司要求我生成自项目开始至今为止每30天的一段时间列表。 示例:项目“A”的开始日期为01 / DEC / 2016,项目“B”的开始日期为2016年2月5日。 今天是07 / FEB / 2017。
输出应该是这样的:
**ITEM | START | END | PERIOD_NO**
----------------------------------------------
A |01/12/2016 |30/12/2016 |0
A |31/12/2016 |29/01/2017 |1
A |30/01/2017 |28/02/2017 |2
B |05/07/2016 |03/08/2016 |0
B |04/08/2016 |02/09/2016 |1
B |03/09/2016 |02/10/2016 |2
B |03/10/2016 |01/11/2016 |3
B |02/11/2016 |01/12/2016 |4
B |02/12/2016 |31/12/2016 |5
B |01/01/2017 |30/01/2017 |6
B |31/01/2017 |01/03/2017 |7
这是我的代码:
select
ITEM
, trunc(Start_Date+(level*30)-30) AS BEGIN
, CASE WHEN (Level-1) = 0 THEN trunc(Start_Date+(level*30) - 1) ELSE trunc(Start_Date+(level*30) -1) END AS END
, Level-1 AS Period
from
(
Select 'A' ITEM
,To_Date('05/07/2016', 'dd/MM/YYYY') Start_Date
, TRUNC(sysdate) END_Date
From Dual
/* UNION ALL
Select
'B' ITEM
, To_Date('01/02/2014', 'dd/MM/YYYY') Start_Date
, TRUNC(sysdate) END_Date
From Dual*/
) t
connect by level < ( ( (END_DATE - START_DATE) / 30) + 1)
因为它仅适用于一件物品,我想征求你的建议如何纠正它以适用于2件或更多件物品。
提前谢谢。
答案 0 :(得分:4)
var test = function(element) {
var tdCaller = $(element);
var parentRow = tdCaller.parent();
var parentBody = parentRow.parent();
// my add
$('tr.mytr.clicked').removeClass('clicked')
parentRow.addClass('clicked');
}
.MarkSelectedRow {
background-color: cornflowerblue;
}
/* my add */
.table-hover tbody tr.mytr.clicked {
background-color: white;
}
答案 1 :(得分:2)
在Oracle 11g及更低版本中,您可以使用嵌套表来实现此目的:
with t (dt) as (
select to_date('01/12/2016','dd/mm/yyyy') from dual union all
select to_date('05/07/2016','dd/mm/yyyy') from dual
)
select
t.dt + (x.column_value - 1) * 30 start_date,
t.dt + x.column_value * 30 - 1 end_date,
x.column_value - 1 period_id
from t cross join table(cast(
multiset(
select level
from dual
connect by t.dt + 30 * (level - 1) <= sysdate
) as sys.odcinumberlist
)) x;
如果您使用的是Oracle 12c +,则可以使用OUTER APPLY
,这极大地简化了语法:
with t (dt) as (
select to_date('01/12/2016','dd/mm/yyyy') from dual union all
select to_date('05/07/2016','dd/mm/yyyy') from dual
)
select
t.dt + (x.n - 1) * 30 start_date,
t.dt + x.n * 30 - 1 end_date,
x.n - 1 period_id
from t outer apply (
select level n
from dual
connect by t.dt + 30 * (level - 1) <= sysdate
) x;
以上查询都会产生:
+------------+-----------+-----------+
| START_DATE | END_DATE | PERIOD_ID |
+------------+-----------+-----------+
| 01-DEC-16 | 30-DEC-16 | 0 |
+------------+-----------+-----------+
| 31-DEC-16 | 29-JAN-17 | 1 |
+------------+-----------+-----------+
| 30-JAN-17 | 28-FEB-17 | 2 |
+------------+-----------+-----------+
| 05-JUL-16 | 03-AUG-16 | 0 |
+------------+-----------+-----------+
| 04-AUG-16 | 02-SEP-16 | 1 |
+------------+-----------+-----------+
| 03-SEP-16 | 02-OCT-16 | 2 |
+------------+-----------+-----------+
| 03-OCT-16 | 01-NOV-16 | 3 |
+------------+-----------+-----------+
| 02-NOV-16 | 01-DEC-16 | 4 |
+------------+-----------+-----------+
| 02-DEC-16 | 31-DEC-16 | 5 |
+------------+-----------+-----------+
| 01-JAN-17 | 30-JAN-17 | 6 |
+------------+-----------+-----------+
| 31-JAN-17 | 01-MAR-17 | 7 |
+------------+-----------+-----------+
以下查询使用分层CONNECT BY
:
select level n
from dual
connect by t.dt + 30 * (level - 1) <= sysdate
下面的CTE是建立一个测试表:
with t (dt) as (
select to_date('01/12/2016','dd/mm/yyyy') from dual union all
select to_date('05/07/2016','dd/mm/yyyy') from dual
)
答案 2 :(得分:1)
Numbers CTE,一些数学和案例陈述
With numbers (NN) as
(
select 0 as NN
from dual
union all
select NN+1
from numbers
where NN < 100
)
, CTE as
(
select item,
StartDate+(NN*30) as StartList,
row_number() over(partition by ITEM order by StartDate+(NN*30)) as PeriodNo
from Numbers
cross join MyTable
where StartDate+(NN*30) < sysdate
)
select Item,
StartList,
case
when StartList +29 > sysdate then sysdate
else StartList +29 > sysdate
end as enddate,
PeriodNo
from CTE