Sql Oracle按组划分为基于日期的序列
我试图使用分区BY OVER来按某些列“分组”行。我对分区的使用有点了解,但是我想按日期“阻塞”分区。例如,如果我们有Sql Oracle按组划分为基于日期的序列,sql,oracle,analytic-functions,Sql,Oracle,Analytic Functions,我试图使用分区BY OVER来按某些列“分组”行。我对分区的使用有点了解,但是我想按日期“阻塞”分区。例如,如果我们有 |col1|col2 | | A |01/JAN/2012| | A |01/FEB/2012| | B |01/MAR/2012| | B |01/APR/2012| | A |01/MAY/2012| 我想用col1进行分区,但我想最后一个A与前两个“不同”,因为它是按日期用“B”行分隔的 如果我使用 它会屈服 但我真正想要的是 这是可能的使用分区超
|col1|col2 |
| A |01/JAN/2012|
| A |01/FEB/2012|
| B |01/MAR/2012|
| B |01/APR/2012|
| A |01/MAY/2012|
我想用col1进行分区,但我想最后一个A与前两个“不同”,因为它是按日期用“B”行分隔的
如果我使用
它会屈服
但我真正想要的是
这是可能的使用分区超过?目前,我已经退回到使用游标来解析数据并分配组id,这样我就可以分离“a”的两个序列,但这相当慢
谢谢
标记。通过几个分析,这是可能的:
select col1, col2, row_number() over (partition by grp order by col2) rnum
from (select col1, col2, max(grp) over(order by col2) grp
from (select col1, col2,
case
when lag(col1) over (order by col2) != col1
then
row_number() over (order by col2)
when row_number() over(order by col2) = 1
then
1
end grp
from data));
i、 e:
首先获取col1按col2日期更改排序的边界:
然后我们可以填充这些空值:
SQL> select col1, col2, max(grp) over(order by col2) grp
2 from (select col1, col2,
3 case
4 when lag(col1) over (order by col2) != col1
5 then
6 row_number() over (order by col2)
7 when row_number() over(order by col2) = 1
8 then
9 1
10 end grp
11 from data);
C COL2 GRP
- --------- ----------
A 01-JAN-12 1
A 01-FEB-12 1
B 01-MAR-12 3
B 01-APR-12 3
A 01-MAY-12 5
然后是通过按col2排序并在grp上分区来分配行数的情况
fiddle:首先,您应该找到每个记录的组ID,以便将所有相似的COL1排序到不同的组(如果它们之间有间隙)。然后在OVER语句中使用此GROUP_ID和COL1:
请看下面我的方法,这与Dazzal的答案相似,逻辑稍有不同: 步骤1:
--find the swhitches to new groups
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data;
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 (null)
B March, 01 2012 1
B April, 01 2012 (null)
A May, 01 2012 1
步骤2:
--identify/mark the groups
select col1, col2, sum(new_grp) over (order by col2) as grp
from(
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data)
;
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 1
B March, 01 2012 2
B April, 01 2012 2
A May, 01 2012 3
步骤3:
--find the row_number within group
select col1, col2, row_number() over(partition by grp order by col2) rn
from(
select col1, col2, sum(new_grp) over (order by col2) as grp
from(
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data
)
);
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 2
B March, 01 2012 1
B April, 01 2012 2
A May, 01 2012 1
您不需要分区。您需要将日期转换为DD/MM/YYYY格式并进行排序。或者,如果你必须的话,你可以用MM部分划分,这会给你01,02,03。。。并且可以根据需要进行分区并轻松转换为数字。但你不需要所有这些。。。不要使你的问题复杂化。始终保持简单。外部查询仅用于将日期重新格式化为DD/MON/YYYY格式:
SELECT val, to_char(to_date(dt, 'DD/MM/YYYY'), 'DD/MON/YYYY') formatted_date
FROM
( -- Format your date to DD/MM/YYYY and order by it --
SELECT 'A' val, to_char(to_date('01/JAN/2012'), 'DD/MM/YYYY') dt FROM dual
UNION
SELECT 'A', to_char(to_date('01/FEB/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'B',to_char(to_date('01/MAR/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'B',to_char(to_date('01/APR/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'A',to_char(to_date('01/MAY/2012'), 'DD/MM/YYYY') FROM dual
ORDER BY 2
)
/
您的日期按照您的要求进行排序,然后:
VAL FORMATTED_DATE
-------------------
A 01/JAN/2012
A 01/FEB/2012
B 01/MAR/2012
B 01/APR/2012
A 01/MAY/2012
谢谢这个@valex这就是我想要的。其他解决方案也有效,但这是最简洁的
--find the swhitches to new groups
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data;
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 (null)
B March, 01 2012 1
B April, 01 2012 (null)
A May, 01 2012 1
--identify/mark the groups
select col1, col2, sum(new_grp) over (order by col2) as grp
from(
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data)
;
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 1
B March, 01 2012 2
B April, 01 2012 2
A May, 01 2012 3
--find the row_number within group
select col1, col2, row_number() over(partition by grp order by col2) rn
from(
select col1, col2, sum(new_grp) over (order by col2) as grp
from(
select col1, col2,
case when nvl(lag(col1) over (order by col2),sysdate) <> col1 then 1 end as new_grp
from data
)
);
COL1 COL2 NEW_GRP
A January, 01 2012 1
A February, 01 2012 2
B March, 01 2012 1
B April, 01 2012 2
A May, 01 2012 1
SELECT val, to_char(to_date(dt, 'DD/MM/YYYY'), 'DD/MON/YYYY') formatted_date
FROM
( -- Format your date to DD/MM/YYYY and order by it --
SELECT 'A' val, to_char(to_date('01/JAN/2012'), 'DD/MM/YYYY') dt FROM dual
UNION
SELECT 'A', to_char(to_date('01/FEB/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'B',to_char(to_date('01/MAR/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'B',to_char(to_date('01/APR/2012'), 'DD/MM/YYYY') FROM dual
UNION
SELECT 'A',to_char(to_date('01/MAY/2012'), 'DD/MM/YYYY') FROM dual
ORDER BY 2
)
/
VAL FORMATTED_DATE
-------------------
A 01/JAN/2012
A 01/FEB/2012
B 01/MAR/2012
B 01/APR/2012
A 01/MAY/2012