我需要创建一个SQL或PLSQL查询来合并和排序表中的数据
我正在尝试创建一个SQL查询,它将帮助我从下面的数据中获得正确的有序输出我需要创建一个SQL或PLSQL查询来合并和排序表中的数据,sql,plsql,gaps-and-islands,Sql,Plsql,Gaps And Islands,我正在尝试创建一个SQL查询,它将帮助我从下面的数据中获得正确的有序输出 Cust num Eff_Date Exp_date 1001 1234 10-01-2010 20-06-2010 1001 1234 20-06-2010 25-06-2010 1001 1234 25-06-2010 12-02-2011 1001 1234 12-02-2011
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
表中的数据:
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
查询的预期输出:
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
我更希望能够使用一条SQL语句完成上述操作。是否可以使用单个SQL语句执行上述操作?有没有其他方法可以做到这一点。这对postgres有效,但可以对oracle稍作修改,IMHO。
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
SELECT
Customer,
`number` AS Number,
MIN(Eff_Date) AS Eff_Date,
MAX(Exp_date) AS Exp_date
FROM tablename
GROUP BY Customer, number
注意:我稍微更改了数据,因为重叠的间隔对我来说似乎不合理
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE lutser
( cust INTEGER NOT NULL
, num iNTEGER NOT NULL
, eff_date DATE NOT NULL
, exp_date DATE NOT NULL
, PRIMARY KEY (cust, num, eff_date)
);
SET datestyle=german;
INSERT INTO lutser(cust,num,eff_date,exp_date) VALUES
(1001,1234,'10-01-2010', '20-06-2010' )
,(1001,1234,'20-06-2010', '25-06-2010' )
,(1001,1234,'25-06-2010', '12-02-2011' )
,(1001,1234,'12-02-2011', '12-02-2011' )
,(1001,3456,'12-02-2011', '25-07-2012' )
,(1001,3456,'25-07-2012', '25-07-2012' )
,(1001,1234,'25-07-2012', '25-08-2012' ) -- added a month to get unique PK
,(1001,1234,'25-08-2012', '31-12-4700' ) -- and here as well
;
VACUUM ANALYZE lutser;
-- SELECT * FROM lutser ORDER BY cust,num,eff_date;
-- EXPLAIN ANALYZE
WITH RECURSIVE island AS
( SELECT cust,num,eff_date,exp_date
FROM lutser l0
WHERE NOT EXISTS
( SELECT *
FROM lutser nx
WHERE nx.cust = l0.cust AND nx.num = l0.num
AND nx.eff_date < l0.eff_date
AND nx.exp_date >= l0.eff_date
)
UNION -- ALL
SELECT isl.cust,isl.num, isl.eff_date,l1.exp_date
FROM lutser l1
JOIN island isl ON isl.cust = l1.cust AND isl.num = l1.num
AND isl.eff_date < l1.eff_date
AND isl.exp_date >= l1.eff_date
)
SELECT DISTINCT ON (cust,num,eff_date) *
FROM island
ORDER BY cust,num,eff_date
;
在Oracle中,我们可以使用分析函数将孤岛分组:
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 20-06-2010
1001 1234 20-06-2010 25-06-2010
1001 1234 25-06-2010 12-02-2011
1001 1234 12-02-2011 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 3456 25-07-2012 25-07-2012
1001 1234 25-07-2012 25-07-2012
1001 1234 25-07-2012 31-12-4700
Cust num Eff_Date Exp_date
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
SQL> select c.cust, c.num, min(eff_date) eff_date, max(exp_Date) exp_date
2 from (select c.cust, c.num, c.eff_date, c.exp_date, max(rn) over (partition by cust, num order by eff_date) grp
3 from (select c.cust, c.num, c.eff_date, c.exp_date,
4 case
5 when lag(exp_date, 1) over (partition by cust, num order by eff_date) != eff_date
6 then
7 row_number() over (partition by cust, num order by eff_date)
8 when row_number() over (partition by cust, num order by eff_date) = 1
9 then
10 1
11 end rn
12 from cust c) c) c
13 group by c.cust, c.num, grp
14 order by eff_date;
CUST NUM EFF_DATE EXP_DATE
---------- ---------- ---------- ----------
1001 1234 10-01-2010 12-02-2011
1001 3456 12-02-2011 25-07-2012
1001 1234 25-07-2012 31-12-4700
SQL>
请添加表格定义好吗?(这将为回复者节省一些打字时间)嗨,谢谢你的回复。但这并不是我想要的。嗨,谢谢你上面的查询。事实上,我有很多数据重叠。这就是我希望创建查询的原因之一。:)我一定会尝试为Oracle修改。谢谢你的帮助