Home » SQL & PL/SQL » SQL & PL/SQL » traverse a table (Oracle 10g)
| traverse a table [message #488114] |
Wed, 05 January 2011 00:44  |
 |
holkudla
Messages: 2 Registered: January 2011 Location: San Jose
|
Junior Member |
|
|
I have a requirement where a view needs to be created to traverse a table that is connected by dates. For example:
table1 has the columns id, status_string, start_date, and end_date.
The row entries would look like this
1, 'continuing', 08/16/2010, 09/15/2010
1, 'started', 06/15/2010, 07/15/2010
5, 'started', 01/01/2010, 02/01/2010
1, 'continuing', 07/16/2010, 08/15/2010
5, 'terminated', 02/02/2010, 02/15/2010
3, 'started', 05/05/2010, 08/08/2011
1, 'terminted', 09/16/2010, 09/17/2010
1, 'started', 11/10/2010, 12/15/2010
I need to create a view that connects the end_date from one row with the start_date of the next row. So my select should result in this exact list returning as represented below. As you can see, the pattern is, current_row.end_date = next_row.start_date - 1 day. Also, the status_string is 'continuing' on the current row. If the status_string is not 'continuing', even if the dates match up, that's just a coincidence.
1, 'started', 06/15/2010, 07/15/2010
1, 'continuing', 07/16/2010, 08/15/2010
1, 'continuing', 08/16/2010, 09/15/2010
1, 'terminted', 09/16/2010, 09/17/2010
1, 'started', 11/10/2010, 12/15/2010
3, 'started', 05/05/2010, 08/08/2011
5, 'started', 01/01/2010, 02/01/2010
5, 'terminated', 02/02/2010, 02/15/2010
thank you, any help would be appreciated.
btw, there are over million rows in this table and it is a legacy system that's been around for 10+ years. So the option to redesigning the table is not a option. Migration would be a monster job just to satisfy this one view we want to write. Also, there are approximately 50+ columns in this table - I'm only representing the relevant columns to the query.
|
|
|
|
| Re: traverse a table [message #488116 is a reply to message #488114] |
Wed, 05 January 2011 00:54   |
 |
Michel Cadot
Messages: 54126 Registered: March 2007 Location: Nanterre, France, http://...
|
Senior Member Account Moderator |
|
|
You posted this in "Suggestions & Feedback" which purpose is "Post your feedback and suggestions for this site (OraFAQ) here. All suggestions, feedback, comments, ideas, etc are more than welcome." Do you think your topic fits this definition? I think it should be posted in "SQL & PL/SQL" forum. Please take care where you create your topic.
Also, Please read OraFAQ Forum Guide, especially "How to format your post?" section.
Make sure that lines of code do not exceed 80 characters when you format.
Indent the code, use code tags and align the columns in result.
Use the "Preview Message" button to verify.
And always post your Oracle version, with 4 decimals (10g is NOT an Oracle version, it is a marketing name, 10.2.0.4 is an Oracle version).
Post a working Test case: create table and insert statements along with the result you want with these data then we will work with your table and data. And take care of the data you post, I don't think that 'terminted' is a correct value (you should add a check constraint on your column).
Regards
Michel
|
|
|
|
| Re: traverse a table [message #488123 is a reply to message #488114] |
Wed, 05 January 2011 02:59   |
lakshmis
Messages: 100 Registered: November 2008 Location: India
|
Senior Member |
|
|
Hi,
DDL and DMLs:
CREATE TABLE tabs(id NUMBER(1), status VARCHAR2(15), start_date DATE, end_date DATE)
INSERT INTO tabs VALUES(1, 'continuing', '08/16/2010', '09/15/2010');
INSERT INTO tabs VALUES(1, 'started', '06/15/2010', '07/15/2010');
INSERT INTO tabs VALUES(5, 'started', '01/01/2010', '02/01/2010');
INSERT INTO tabs VALUES(1, 'continuing', '07/16/2010', '08/15/2010');
INSERT INTO tabs VALUES(5, 'terminated', '02/02/2010', '02/15/2010');
INSERT INTO tabs VALUES(3, 'started', '05/05/2010', '08/08/2011');
INSERT INTO tabs VALUES(1, 'terminted', '09/16/2010', '09/17/2010');
INSERT INTO tabs VALUES(1, 'started', '11/10/2010', '12/15/2010');
I tried using START WITH and CONNECT BY:
SELECT id,status,start_date,end_date FROM tabs START WITH start_date='06/15/2010'
OR status='started'
CONNECT BY start_date=PRIOR end_date+1
But the order of the result I got vary from your requirement. And I could not order them.
Output:
1 started 06/15/2010 07/15/2010
1 continuing 07/16/2010 08/15/2010
1 continuing 08/16/2010 09/15/2010
1 terminted 09/16/2010 09/17/2010
5 started 01/01/2010 02/01/2010
5 terminated 02/02/2010 02/15/2010
3 started 05/05/2010 08/08/2011
1 started 11/10/2010 12/15/2010
Regards,
Lakshmi.
|
|
|
|
| Re: traverse a table [message #488127 is a reply to message #488123] |
Wed, 05 January 2011 03:37   |
cookiemonster
Messages: 9135 Registered: September 2008 Location: Rainy Manchester
|
Senior Member |
|
|
Do not create tables called tabs - there's a data dictionary view of that name.
Always use to_Date with the correct format mask for dates. Just because it works for you doesn't mean it'll work for everybody else:
SQL> CREATE TABLE tabs1 (id NUMBER(1), status VARCHAR2(15), start_date DATE, end_date DATE);
Table created.
SQL> INSERT INTO tabs1 VALUES(1, 'continuing', '08/16/2010', '09/15/2010');
INSERT INTO tabs1 VALUES(1, 'continuing', '08/16/2010', '09/15/2010')
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
|
|
|
|
| Re: traverse a table [message #488130 is a reply to message #488127] |
Wed, 05 January 2011 03:51   |
lakshmis
Messages: 100 Registered: November 2008 Location: India
|
Senior Member |
|
|
Hi,
Modified DDL and DMLs:
CREATE TABLE test_tab(id NUMBER(1), status VARCHAR2(15), start_date DATE, end_date DATE)
INSERT INTO test_tab VALUES(1, 'continuing', TO_DATE('08/16/2010','MM/DD/YYYY'),TO_DATE('09/15/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(1, 'started', TO_DATE('06/15/2010','MM/DD/YYYY'),TO_DATE('07/15/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(5, 'started', TO_DATE('01/01/2010','MM/DD/YYYY'),TO_DATE('02/01/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(1, 'continuing',TO_DATE('07/16/2010','MM/DD/YYYY'),TO_DATE('08/15/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(5, 'terminated',TO_DATE('02/02/2010','MM/DD/YYYY'),TO_DATE('02/15/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(3, 'started', TO_DATE('05/05/2010','MM/DD/YYYY'),TO_DATE('08/08/2011','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(1, 'terminted',TO_DATE('09/16/2010','MM/DD/YYYY'),TO_DATE('09/17/2010','MM/DD/YYYY'));
INSERT INTO test_tab VALUES(1, 'started', TO_DATE('11/10/2010','MM/DD/YYYY'),TO_DATE('12/15/2010','MM/DD/YYYY'));
I just want to know is there any other method apart from START WITH..CONNECT BY to arrive at these results in SQL.
Regards,
Lakshmi.
|
|
|
|
| Re: traverse a table [message #488133 is a reply to message #488114] |
Wed, 05 January 2011 03:56   |
ayush_anand
Messages: 417 Registered: November 2008
|
Senior Member |
|
|
SQL> select * from tabs order by 1,3;
ID STATUS START_DATE END_DATE
---------- --------------- ---------- ----------
1 started 06/15/2010 07/15/2010
1 continuing 07/16/2010 08/15/2010
1 continuing 08/16/2010 09/15/2010
1 terminted 09/16/2010 09/17/2010
1 started 11/10/2010 12/15/2010
3 started 05/05/2010 08/08/2011
5 started 01/01/2010 02/01/2010
5 terminated 02/02/2010 02/15/2010
8 rows selected.
looks to me simple order by
|
|
|
|
|
|
|
|
| Re: traverse a table [message #488224 is a reply to message #488219] |
Wed, 05 January 2011 11:51   |
 |
Michel Cadot
Messages: 54126 Registered: March 2007 Location: Nanterre, France, http://...
|
Senior Member Account Moderator |
|
|
Yes it works:
SQL> select id, status, start_date, end_date
2 from test_tab
3 connect by prior end_date = start_date-1 and prior id = id
4 start with status = 'started'
5 /
ID STATUS START_DATE END_DATE
---------- --------------- ---------- ----------
5 started 01/01/2010 01/02/2010
5 terminated 02/02/2010 15/02/2010
3 started 05/05/2010 08/08/2011
1 started 15/06/2010 15/07/2010
1 continuing 16/07/2010 15/08/2010
1 continuing 16/08/2010 15/09/2010
1 terminted 16/09/2010 17/09/2010
1 started 10/11/2010 15/12/2010
Regards
Michel
[Updated on: Wed, 05 January 2011 11:52] Report message to a moderator
|
|
|
|
| Re: traverse a table [message #488226 is a reply to message #488219] |
Wed, 05 January 2011 11:55   |
cookiemonster
Messages: 9135 Registered: September 2008 Location: Rainy Manchester
|
Senior Member |
|
|
You could just change the table name and column names to something else. So long as we've got something that creates tables and data that accurately reflects your problem we couldn't care less what it's called.
Just keep it simple - include only the relevant columns.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Re: traverse a table [message #570472 is a reply to message #488224] |
Sat, 10 November 2012 07:20   |
Solomon Yakobson
Messages: 1397 Registered: January 2010
|
Senior Member |
|
|
Michel Cadot wrote on Wed, 05 January 2011 12:51Yes it works:
But it needs additional condition. Otherwise it will not work right if same id started again next day after:
SQL> update test_tab
2 set start_date = date '2010-09-18' where start_date = date '2010-11-10'
3 /
1 row updated.
SQL> select * from test_tab order by id,start_date
2 /
ID STATUS START_DAT END_DATE
---------- --------------- --------- ---------
1 started 15-JUN-10 15-JUL-10
1 continuing 16-JUL-10 15-AUG-10
1 continuing 16-AUG-10 15-SEP-10
1 terminted 16-SEP-10 17-SEP-10
1 started 18-SEP-10 15-DEC-10
3 started 05-MAY-10 08-AUG-11
5 started 01-JAN-10 01-FEB-10
5 terminated 02-FEB-10 15-FEB-10
8 rows selected.
SQL> select id, status, start_date, end_date
2 from test_tab
3 connect by prior end_date = start_date-1 and prior id = id
4 start with status = 'started'
5 /
ID STATUS START_DAT END_DATE
---------- --------------- --------- ---------
5 started 01-JAN-10 01-FEB-10
5 terminated 02-FEB-10 15-FEB-10
3 started 05-MAY-10 08-AUG-11
1 started 15-JUN-10 15-JUL-10
1 continuing 16-JUL-10 15-AUG-10
1 continuing 16-AUG-10 15-SEP-10
1 terminted 16-SEP-10 17-SEP-10
1 started 18-SEP-10 15-DEC-10
1 started 18-SEP-10 15-DEC-10
9 rows selected.
SQL> select id, status, start_date, end_date
2 from test_tab
3 start with status = 'started'
4 connect by prior end_date = start_date - 1
5 and prior id = id
6 and status != 'started'
7 /
ID STATUS START_DAT END_DATE
---------- --------------- --------- ---------
5 started 01-JAN-10 01-FEB-10
5 terminated 02-FEB-10 15-FEB-10
3 started 05-MAY-10 08-AUG-11
1 started 15-JUN-10 15-JUL-10
1 continuing 16-JUL-10 15-AUG-10
1 continuing 16-AUG-10 15-SEP-10
1 terminted 16-SEP-10 17-SEP-10
1 started 18-SEP-10 15-DEC-10
8 rows selected.
SQL>
SY.
|
|
|
|
|
|
|
|
|
|
|
|
Goto Forum:
Current Time: Sat May 18 15:06:01 CDT 2013
Total time taken to generate the page: 1.04241 seconds
|