splitting string - oracle sql syntax

please see the attached spreadheet which shows

fig 1.  current output from tbl_marks (select * from tbl_marks where stud_id = 222648)
this table records student attendance over the academic year. both morning (AM) and afternoon (PM) marks are recorded (so there are two characters for each day). there are around 730 characters in each mark string (365 days * 2)

fig2. desired output 1
each students daily attendance on one row (AM mark and PM mark).

fig2. desired output 2
each students morning and afternoon attendance on a separate row .

any help to write both queries is appreciated.
ee-example.xlsx
tonMachine100Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

PortletPaulfreelancerCommented:
What a  nicely prepared and utterly clear question! Thank you.

Could I ask for some "raw data" from [TBL_MARKS] please (not an image)
0
Guy Hengel [angelIII / a3]Billing EngineerCommented:
please check out this page to split your string (marks) into rows:
http://www.oracle-developer.net/display.php?id=412
0
tonMachine100Author Commented:
Guy - thanks for the link, i'll check it out.

PortletPaul - heres an updated version of the attachment - this time with raw data.
ee-example-with-data.xlsx
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

sdstuberCommented:
I made the assumption from your example that the desired output  was not correct for 309518.

The other two IDs have date sequences that begin on their start_date.  That one does not.

Also I went up to 366 and 732 to support the extra day in leap years


SELECT id,
       stud_id,
       attendance_date,
       am_mark,
       pm_mark
  FROM (SELECT n,
               id,
               stud_id,
               start_date + n - 1 attendance_date,
               SUBSTR(marks, n * 2 - 1, 1) am_mark,
               SUBSTR(marks, n * 2, 1) pm_mark,
               marks
          FROM tbl_marks,
               (    SELECT LEVEL n
                      FROM DUAL
                CONNECT BY LEVEL <= 366))
 WHERE n * 2 <= LENGTH(marks);

Open in new window


SELECT id,
       stud_id,
       attendance_date,
       am_pm,
       mark
  FROM (SELECT n,
               id,
               stud_id,
               start_date + n - 1 attendance_date,
               CASE WHEN MOD(n, 2) = 1 THEN 'am' ELSE 'pm' END am_pm,
               SUBSTR(marks, n, 1) mark,
               marks
          FROM tbl_marks,
               (    SELECT LEVEL n
                      FROM DUAL
                CONNECT BY LEVEL <= 732))
 WHERE n <= LENGTH(marks);

Open in new window

0
PortletPaulfreelancerCommented:
No points please.
Thanks for the actual values. Either query by sdstuber above will work

The marking system produces these combinations:
| AM_MARK | PM_MARK | OCCURS |
|---------|---------|--------|
|       # |       # |    518 |
|       / |       \ |    489 |
|       L |       \ |      8 |
|       M |       M |      5 |
|       / |       B |      1 |
|       / |       V |      1 |
|       H |       H |      9 |
|       M |       I |      1 |
|       / |       I |      1 |
|       X |       X |      6 |
|       C |       C |      1 |
|       Y |       Y |      1 |
|       I |       I |     50 |

http://sqlfiddle.com/#!4/fec06/9

Open in new window

0
tonMachine100Author Commented:
thanks guys, but i've found an issue.

I've run the second query (where ID = 309518):

SELECT id,
       stud_id,
       attendance_date,
       am_pm,
       mark
  FROM (SELECT n,
               id,
               stud_id,
               start_date + n - 1 attendance_date,
               CASE WHEN MOD(n, 2) = 1 THEN 'am' ELSE 'pm' END am_pm,
               SUBSTR(marks, n, 1) mark,
               marks
          FROM tbl_marks,
               (    SELECT LEVEL n
                      FROM DUAL
                CONNECT BY LEVEL <= 732)
       
       where
        ID = 309518
       
       )
 WHERE n <= LENGTH(marks);

Open in new window

This is the output:
|     ID | STUD_ID |                  ATTENDANCE_DATE | AM_PM | MARK |
|--------|---------|----------------------------------|-------|------|
| 309518 |  222648 | September, 04 2006 00:00:00+0000 |    am |    X |
| 309518 |  222648 | September, 05 2006 00:00:00+0000 |    pm |    X |
| 309518 |  222648 | September, 06 2006 00:00:00+0000 |    am |    / |
| 309518 |  222648 | September, 07 2006 00:00:00+0000 |    pm |    \ |
| 309518 |  222648 | September, 08 2006 00:00:00+0000 |    am |    / |
| 309518 |  222648 | September, 09 2006 00:00:00+0000 |    pm |    \ |
| 309518 |  222648 | September, 10 2006 00:00:00+0000 |    am |    / |

Open in new window



You'll notice the incorrect date is appearing against the mark. each date should appear twice (for both its AM and PM mark). The code is outputting the date just once.

thanks
0
sdstuberCommented:
oops sorry about that, forgot to include the division


SELECT id,
       stud_id,
       attendance_date,
       am_pm,
       mark,
       marks
  FROM (SELECT n,
               id,
               stud_id,
               start_date + FLOOR((n - 1) / 2) attendance_date,   --- this line is what I changed
               CASE WHEN MOD(n, 2) = 1 THEN 'am' ELSE 'pm' END am_pm,
               SUBSTR(marks, n, 1) mark,
               marks
          FROM tbl_marks,
               (    SELECT LEVEL n
                      FROM DUAL
                CONNECT BY LEVEL <= 732))
 WHERE n <= LENGTH(marks);
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tonMachine100Author Commented:
Thanks. You've all been a great help
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Query Syntax

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.