按顺序的值分组
Posted
技术标签:
【中文标题】按顺序的值分组【英文标题】:Group by values that are in sequence 【发布时间】:2012-04-02 13:27:56 【问题描述】:我有一些这样的桌子
row chequeNo
1 15
2 19
3 20
4 35
5 16
我需要得到这样的结果
row from to
1 15 16
2 19 20
3 35 35
所以我需要 chequeNo
组,其中的值是连续的,没有任何中断。 chequeNo
是唯一列。此外,它应该使用一个 sql 选择查询来完成,因为除了选择查询之外,我没有创建任何 sql 结构的权限。
那么有可能吗?
如果有任何帮助,将不胜感激
【问题讨论】:
你使用的数据库是? 要么你的例子没有意义,要么我遗漏了一些东西 你确定你上面写的期望结果是正确的吗?我看不出它有什么规律。 你应该提供一个规则来解释你需要如何选择(从)/计算(到)值。在当前的形式中,无法得出任何规则。 为什么第 3 行从 35 开始?,不应该从 20 或 21 开始吗? 【参考方案1】:您可以在此处使用名为 Tabibitosan 的 Aketi Jyuuzou 技术:
SQL> create table mytable (id,chequeno)
2 as
3 select 1, 15 from dual union all
4 select 2, 19 from dual union all
5 select 3, 20 from dual union all
6 select 4, 35 from dual union all
7 select 5, 16 from dual
8 /
Table created.
SQL> with tabibitosan as
2 ( select chequeno
3 , chequeno - row_number() over (order by chequeno) grp
4 from mytable
5 )
6 select row_number() over (order by grp) "row"
7 , min(chequeno) "from"
8 , max(chequeno) "to"
9 from tabibitosan
10 group by grp
11 /
row from to
---------- ---------- ----------
1 15 16
2 19 20
3 35 35
3 rows selected.
问候, 抢。
【讨论】:
+1 感谢提供该技术的名称,这一点额外信息将“这是你的答案 1308044”转换为“这是你应该知道的一般技术”。 非常感谢。我已将此解决方案集成到实际查询中,现在可以正常工作了。【参考方案2】:这应该适用于 Oracle 10(仅在 Oracle 11 上测试过)
select group_nr + 1,
min(chequeno) as start_value,
max(chequeno) as end_value
from (
select chequeno,
sum(group_change_flag) over (order by rn) as group_nr
from (
select row_number() over (order by chequeno) as rn,
chequeno,
case
when chequeno - lag(chequeno,1,chequeno) over (order by chequeno) <= 1 then 0
else 1
end as group_change_flag
from foo
) t1
) t2
group by group_nr
order by group_nr
(它应该适用于任何支持标准 SQL 窗口函数的 DBMS,例如 PostgreSQL、DB2、SQL Server 2012)
【讨论】:
【参考方案3】:这是一种“普通的”方法:
SELECT T1.chequeNo, T2.chequeNo
FROM Table1 AS T1 INNER JOIN Table1 AS T2 ON T2.chequeNo >= T1.chequeNo
WHERE
NOT EXISTS (SELECT T0.chequeNo FROM Table1 T0 WHERE T0.chequeNo IN ((T1.chequeNo-1), (T2.chequeNo+1)))
AND (SELECT COUNT(*) FROM Table1 T0 WHERE T0.chequeNo BETWEEN T1.chequeNo AND T2.chequeNo)=(T2.chequeNo - T1.chequeNo + 1)
ORDER BY 1,2
如果对于大型数据集效率太低,请告诉我。
【讨论】:
【参考方案4】:CREATE TABLE YOUR_TABLE (
chequeNo NUMBER PRIMARY KEY
);
INSERT INTO YOUR_TABLE VALUES (15);
INSERT INTO YOUR_TABLE VALUES (19);
INSERT INTO YOUR_TABLE VALUES (20);
INSERT INTO YOUR_TABLE VALUES (35);
INSERT INTO YOUR_TABLE VALUES (16);
SELECT T1.chequeNo "from", T2.chequeNo "to"
FROM
(
SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN
FROM (
SELECT chequeNo, LAG(chequeNo) OVER (ORDER BY chequeNo) PREV
FROM YOUR_TABLE
)
WHERE PREV IS NULL OR chequeNo > PREV + 1
) T1
JOIN
(
SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN
FROM (
SELECT chequeNo, LEAD(chequeNo) OVER (ORDER BY chequeNo) NEXT
FROM YOUR_TABLE
)
WHERE NEXT IS NULL OR chequeNo < NEXT - 1
) T2
USING (RN);
结果:
from to
---------------------- ----------------------
15 16
19 20
35 35
如果我们加点调料...
INSERT INTO YOUR_TABLE VALUES (17);
INSERT INTO YOUR_TABLE VALUES (18);
...我们得到:
from to
---------------------- ----------------------
15 20
35 35
【讨论】:
以上是关于按顺序的值分组的主要内容,如果未能解决你的问题,请参考以下文章