SQL Query gives unusual results when writing out column data explicitly (Snowflake)

Viewed 69

I have come across a SQL oddity wherein replacing explicit strings with column names of an existing row in the table doesn't give the same result! I have looked this query over for a good hour, and while I'm sure there is a silly mistake somewhere, it's just not appearing. I would be very grateful for a tip!

This is in SQL Snowflake (similar to postgresql)

The basic structure of the query is essentially this:

SELECT ...,
WHEN EXISTS(
    SELECT ...
    FROM many_joins_table MJT
    WHERE MJT.col1 like '%' || GL.year || '%'
      AND MJT.col2 like '%' || GL.maker || '%'
      AND MJT.col3 like '%' || GL.set_name || '%'
      AND MJT.col4 like '%' || GL.card_number || '%'
    )
THEN 'YES'
ELSE 'NO'
END
FROM gradingledger GL

The following row exists in the gradingledger table:

SELECT * 
FROM gradingledger
WHERE gl.year = '1996' and gl.maker = 'Topps' and gl.set_name = 'Finest' and gl.card_number = '122'

(gives one-row result)

The issue is that when making the following replacements in the query:

  • GL.year with '1996',
  • GL.maker with 'Topps',
  • GL.set_name with 'Finest', and
  • GL.card_number with '122' ,

the EXISTS column in the result then changes its value from YES to NO. In fact, the EXISTS column should always have given 'NO', because that entry does not exist in the joined table! But either way, I do not see how it would change its mind.

I don't think my example above is enough to narrow down the issue, so here is the actual query below.

SELECT 
    gl.year, 
    gl.maker, 
    gl.set_name, 
    gl.card_number,
    CASE
    WHEN EXISTS (
        SELECT CSetSC.certnumber
        FROM competitivecategories CC
            inner join competitivesubcategories CSC  on CC.competitivecategoryid = CSC.competitivecategoryid
            inner join competitivesettypegroups CSTG on CSC.competitivesubcategoryid = CSTG.competitivesubcategoryid
            inner join competitivesettypes CST on CSTG.competitivesettypegroupid = CST.competitivesettypegroupid
            inner join competitiveslots CSlots on CST.competitivesettypeid = CSlots.competitivesettypeid
            inner join competitiveslotsportscards CSlotSC on CSlotSC.competitiveslotid = CSlots.competitiveslotid
            inner join competitivesetsportscards CSetSC on CSetSC.competitiveslotsportscardid = CSlotSC.competitiveslotsportscardid
            inner join gradingledger gl on CSetSC.certnumber = gl.certnumber
//        where   CST.settypename ilike '%' || '1996' || '%'
        where   CST.settypename ilike '%' || gl.year || '%'
//            and CST.settypename ilike '%' || 'Topps' || '%'
            and CST.settypename ilike '%' || gl.maker || '%'
            and 
                case
                when CST.settypename is null then true
//                when CST.settypename ilike '%' || 'Finest' || '%' then true
                when CST.settypename ilike '%' || gl.set_name || '%' then true
                else false
                end
//            and CSlots.slotname ilike '%' || '122' || '%'
            and CSlots.slotname ilike '%' || gl.card_number || '%'
        )
    then 'YES'
    else 'NO'
    end as card_and_set_already_in_registry
from grading_ledger gl
where gl.year = '1996' and gl.maker = 'Topps' and gl.set_name = 'Finest' and gl.card_number = '122'

It returns one row, with the word 'YES' in the last column, and if the commented rows are used instead, then it returns 'NO' in the last column.

Thank you for the help!

1 Answers

one reason might be that you are selecting from two different tables. grading_ledger and gradingledger or that could a typo

Another reason might be your "row checking SQL" does not match the WHERE SQL of the inner table, because for set_name you also allow matching on null via the first row of your CASE. For 'makerandset_name` the inner SQL uses a case insensitive search that also allows sub-string matching.

so the row check SQL should be:

SELECT * 
FROM gradingledger
WHERE gl.year = '%1996%' 
and gl.maker ilike '%Topps%' 
and (gl.set_name ilike '%Finest%' or gl.set_name is null)
and (gl.card_number = '%122%'

If that still only give one row, then more harder thinking will be required, but I suspect the above is the root of the problem.

Related