简体   繁体   中英

Is there a way to make this case statement work?

I am getting the following error with the code below:

ERROR: argument of AND must be type boolean, not type character varying LINE 9: and case ^ SQL state: 42804 Character: 300

This code does a few things, but what I am having trouble with is the case statment. I want this piece to look for instances where the first 11 characters of two strings match. If that is not true for a given record, then look at the first 10 characters, then 9, then 8. After that, null is an acceptable result.

select cm.course_id, cm.course_name, cmp.course_id as parentcourse, 
(select cmm.course_id
from course_main cmm
where cmm.course_id ilike '%Master%'
    and cmm.course_id not ilike '%Ground%'
    and cmm.course_id not ilike '%Surprise%'
    and cmm.course_id not ilike '%emba%'
    and cmm.row_status != 2
    and case 
         when left(cm.course_id,11) = left(cmm.course_id,11) 
            then cmm.course_id 
            else 
            case 
            when left(cm.course_id,10) = left(cmm.course_id, 10) 
                then cmm.course_id 
                else 
                case 
                when left(cm.course_id,9) = left(cmm.course_id, 9) 
                    then cmm.course_id 
                    else 
                    case 
                    when left(cm.course_id,8) = left(cmm.course_id,8) 
                        then cmm.course_id 

                    end
                end
            end
        end) as mastercourse
from course_main as cm
left join course_course cc
on cc.crsmain_pk1 = cm.pk1
left join course_main cmp
on cmp.pk1 = cc.crsmain_parent_pk1
where cm.course_id ilike '%-ES-2020-%'
    and cm.row_status != 2
    and cmp.course_id is null
    order by cm.course_id;

Thank you for the assistance, Z4. I took a shot at applying your suggestions and was able to get past the error. The problem with these strings is that I am trying to match something like:

'NRSG-46009-ES-2020-OA' to 'NRSG-46009-Master-Online-Content' in an environment that also contains these:

'NRSG-46006-Master-Online-Content' 'NRSG-46003-Master-Online-Content' 'NRSG-4600-Master-Online-Content'

If I look at the first 8 characters before looking at the first 11, I will get mismatches. So, I am looking at 11 first. If there is nothing that matches, look at the first ten, and so on. Strings of 8 are the floor in our ID schema with examples like this:

'IT-7003-ES-2019-AE' that needs to be matched with 'IT-7003-Master-Online-Content'

Anyway, I took your advice and ran the following:

select distinct cm.course_id, cm.course_name, cmp.course_id as parentcourse, 
case 
when left(cm.course_id,11) = left(cmm.course_id,11) 
    then cmm.course_id 
    else 
    case 
    when left(cm.course_id,10) = left(cmm.course_id, 10) 
        then cmm.course_id 
        else 
        case 
        when left(cm.course_id,9) = left(cmm.course_id, 9) 
            then cmm.course_id 
            else 
            case 
            when left(cm.course_id,8) = left(cmm.course_id,8) 
                then cmm.course_id 
            end
        end
    end
end as mastercourse
from course_main cm
    left join course_course cc
        on cc.crsmain_pk1 = cm.pk1
    left join course_main cmp
        on cmp.pk1 = cc.crsmain_parent_pk1
    left join course_main cmm
        on cm.pk1 = cm.pk1
where cm.course_id ilike '%-ES-2020-%'
    and cm.row_status != 2
    and cmp.course_id is null
    and cmm.course_id ilike '%Master%'
    and cmm.course_id not ilike '%Ground%'
    and cmm.course_id not ilike '%Surprise%'
    and cmm.course_id not ilike '%emba%'
    and cmm.row_status != 2
    order by cm.course_id;

This seems to be working, but I am getting duplicate results:

results of 'successful' query

Any ideas on how I can exclude the duplicates?

First, there is really no need to use such a complex case statement. If the first 8 characters do not match, then certainly the first 9, or 10 or 11 are not going to match either, right? So just get rid of the whole thing and check only the first 8:

CASE
  WHEN LEFT(cm.course_id, 8) = LEFT(cmm.course_id, 8)
    THEN cmm.course_id
END

Next, the CASE statement needs to come out of the WHERE clause and into the SELECT list (this is what is causing the boolean type error):

select
  [...]
  (
    select
      CASE
        WHEN LEFT(cm.course_id, 8) = LEFT(cmm.course_id, 8)
          THEN cmm.course_id
      END
    from 
      course_main cmm
    where 
      cmm.course_id ilike '%Master%'
      and cmm.course_id not ilike '%Ground%'
      and cmm.course_id not ilike '%Surprise%'
      and cmm.course_id not ilike '%emba%'
      and cmm.row_status != 2
  ) as mastercourse
FROM
  [...]

I don't know anything about the data that you're trying to capture here, but I would also strongly suggest taking some time to rethink the use of a correlated subquery. Even if this is correctly describing the data set you want, the subquery is really inefficient. I would guess that it can probably be replaced entirely by a LEFT JOIN in the main query body (likely a self join from course_main to itself).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM