0

i keep data on table rows as followed like this;

t_course

+------+------------------------------------------+
| sid  |  courses                                 |
+------+------------------------------------------+
|  1   |  cs101.math102.ns202-2.phy104            |
+------+------------------------------------------+
|  2   |  cs101.math201.ens202-1.phy104-10.chm105 |
+------+------------------------------------------+
|  3   |  cs101.ns202-2.math201.ens202-1.phy104   |
+------+------------------------------------------+

Now, i want to take the sum of courses mentioned ns202 and ens202 in same time. Normally it should only brings record which id is 3, it brings all of the records (because of instr). i have used many methods for this, but it doesn't work. For example;

select count(*) from 
   t_course 
      where 
            instr(courses, 'ns202')  > 0 
        and instr(courses, 'ens202') > 0;

Above code doesn't work properly because it takes ns202 but ens202 contains ns202 in itself.

I tried using regular expressions, i converted all course to row (split) but this has both broke working logic and slowed down.

How can i do this with regular expressions instead of instr according to begin withs (for example ns202%) logic? (Begining with ns202 first or after dot)

6
  • do you want rows which have both ns202 and ens202 ? Commented Dec 28, 2016 at 21:26
  • @vkp, Yes, i want to only sum of records which contains both ns202 and ens202. Commented Dec 28, 2016 at 21:28
  • what do you mean by sum of records here? Commented Dec 28, 2016 at 21:29
  • For example there is only total one record according to this case(both ns202 and ens202) in my table. Commented Dec 28, 2016 at 21:32
  • 2
    Why is your input data in that format in the first place? First Normal Form is violated - the most basic requirement of relational tables. The reason you even have to think about such things (instead of a much, much simpler query) is that a single "value" contains multiple "actual values". Commented Dec 28, 2016 at 21:39

2 Answers 2

2

You can use regexp_like with word boundaries to get rows which have both ns202 and ens_202. Normally you would use \b for word-boundaries. As Oracle doesn't support it, the alternate is to use (\s|\W) with start ^ and end $ anchors.

\s - space character, \W - non word character. Add more characters as needed, as word-boundaries based on your requirements.

select *
from t_course   
where regexp_like(courses,'(^|\s|\W)ns202(\s|\W|$)') 
and regexp_like(courses,'(^|\s|\W)ens202(\s|\W|$)')
Sign up to request clarification or add additional context in comments.

Comments

1

You will have the same problem with ens202, by the way - what if there is also cens202or tens202?

You can solve your problem with regular expressions. You can also solve it with the LIKE operator:

select <whatever>
from   <table or tables>
where (courses like 'ns202%' or courses like '%.ns202%')
  and (courses like 'ens202%' or courses like '%.ens202%')

You can test both approaches to see which works best for your data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.