我遇到以下问题时出现问题:
SELECT
B.EMPLOYEE_NAME,
A.START_DATE+(LEVEL-1) AS INDIVIDUAL_DAY,
TO_CHAR(A.START_DATE,'MM/DD/YYYY') START_DATE,
TO_CHAR(A.END_DATE,'MM/DD/YYYY') END_DATE
FROM table1 A
INNER JOIN table2 B ON A.EMPLOYEE_NAME = B.EMPLOYEE_NAME
CONNECT BY LEVEL-1 <= (A.END_DATE-A.START_DATE);
如果表A中只有一条记录,那么我就能得到我正在寻找的记录。但是,如果有多个记录,那么我会得到过多的结果。
我在寻找什么:
我有一个包含EMPLOYEE_NAME
,START_DATE
和END_DATE
字段的行的表格。我想将这一行信息转换成多行。例如:
当前 -
NAME START END
DAVID SMITH 1-1-2001 1-6-2011
JOHN SMITH 2-7-2012 2-9-2012
渴望 -
NAME DATE
DAVID SMITH 1-1-2001
DAVID SMITH 1-2-2001
DAVID SMITH 1-3-2001
DAVID SMITH 1-4-2001
DAVID SMITH 1-5-2001
DAVID SMITH 1-6-2001
JOHN SMITH 2-7-2012
JOHN SMITH 2-8-2012
JOHN SMITH 2-9-2012
关于如何实现这一目标的任何想法? 注意:我正在使用Oracle 10和11。
答案 0 :(得分:3)
在10g / 11g中你可以使用model子句。
SQL> with emps as (select rownum id, name, start_date,
2 end_date, trunc(end_date)-trunc(start_date) date_range
3 from table1)
4 select name, the_date
5 from emps
6 model partition by(id as key)
7 dimension by(0 as f)
8 measures(name, start_date, cast(null as date) the_date, date_range)
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
NAME THE_DATE
----------- ----------
DAVID SMITH 01-01-2001
DAVID SMITH 01-02-2001
DAVID SMITH 01-03-2001
DAVID SMITH 01-04-2001
DAVID SMITH 01-05-2001
DAVID SMITH 01-06-2001
JOHN SMITH 02-07-2012
JOHN SMITH 02-08-2012
JOHN SMITH 02-09-2012
9 rows selected.
即您的基本查询:
select rownum id, name, start_date,
end_date, trunc(end_date)-trunc(start_date) date_range
from table1
只定义日期+范围(我使用了rownum id,但如果你有PK,你可以使用它。
分区按ID分配我们的计算(唯一行):
6 model partition by(id as key)
措施:
8 measures(name, start_date, cast(null as date) the_date, date_range)
定义我们将输出/计算的属性。在这种情况下,我们使用name,start_date加上要生成的行范围。另外我已经定义了一个列the_date
来保存计算日期(即我们想要计算start_date + n,其中n从0到该范围。
规则定义我们将如何填充我们的列:
9 rules (the_date [for f from 0 to date_range[0] increment 1] = start_date[0] + cv(f),
10 name[any] = name[0]);
所以
the_date [for f from 0 to date_range[0] increment 1]
我们说我们将生成date_range保持的行数+ 1(即总共6个日期)。可以通过f
(当前值)函数引用cv
的值。
所以在大卫的第1行,我们有the_date [0] = start_date+0
,随后在第2行,我们有the_date [1] = start_date+1
。一直到start_date + 5(即end_date
)
P.S。 连接你需要做这样的事情:
select
A.EMPLOYEE_NAME,
A.START_DATE+(b.r-1) AS INDIVIDUAL_DAY,
TO_CHAR(A.START_DATE,'MM/DD/YYYY') START_DATE,
TO_CHAR(A.END_DATE,'MM/DD/YYYY') END_DATE
FROM table1 A
cross join (select rownum r
from (select max(end_date-start_date) d from table1)
connect by level-1 <= d) b
where A.START_DATE+(b.r-1) <= A.END_DATE
order by 1, 2;
即。将connect连接到子查询,然后过滤出individual_day&gt;的行。 END_DATE。
但我不推荐这种方法。与模型方法相比,它的性能会更差(特别是如果范围变大)。
答案 1 :(得分:3)
不寻找分数。找到你的帖子并做这个无聊...
我的测试表:
EMPNO ENAME START_DATE END_DATE
------------------------------------------
7369 SMITH 6/1/2011 6/7/2011
7499 ALLEN 7/1/2011 7/3/2011
SELECT ename, ind_start_date
FROM
(
SELECT distinct ename
, start_date
, to_char(start_date + (LEVEL-1), 'MM/DD/YYYY') ind_start_date
, to_char(end_date, 'MM/DD/YYYY') end_date
FROM emp_test
WHERE ename IN ('SMITH', 'ALLEN')
CONNECT BY LEVEL <= (end_date-start_date)+1
ORDER BY ename
)
/
ENAME IND_START_DATE
--------------------------
ALLEN 07/01/2011
ALLEN 07/02/2011
ALLEN 07/03/2011
SMITH 06/01/2011
SMITH 06/02/2011
SMITH 06/03/2011
SMITH 06/04/2011
SMITH 06/05/2011
SMITH 06/06/2011
SMITH 06/07/2011
保持简单......