tags:

views:

93

answers:

4

I'd like to be able to set add a field that answers the question "For a value in this record, does that value meet some condition in another table?". I thought I'd try a case-when with an exists, but Teradata (my dbms) does not like it. Any recommendations?

select foo,
   (case when exists (select x.foo
                      from somedb x
                      where x.bar > 0)
    then '1' else '0' end) as MyFlag

from mydb
+8  A: 

It looks like you're missing the END for the CASE statement?

select foo,
   (case when exists (select x.foo
                      from somedb x
                      where x.bar > 0)
    then '1' else '0' END) as MyFlag

from mydb
martin clayton
Good answer. Often it is the easy answers that are needed.
Jürgen Hollfelder
Good answer, but from Chris's subsequent comment to his original question it looks as though he did include the END in the original CASE statement.
Mark Bannister
Yep, I do have the END, there. Let me go edit that...
Chris
+1  A: 

There is probably more than one solution to this. Sometimes there is a relationship between the two tables. Then I make a JOIN and handle it in the WHERE clause. I do not know Teradata but in Oracle I can also do something like this.

SELECT foo 
FROM   mydb
WHERE  (select count(*) from somedb where x.bar > 0) > 0

or maybe more like your code

select foo,  
   (case when (select count(*)
                      from somedb x  
                      where x.bar > 0) > 0   
    then '1' else '0') as MyFlag       
from mydb

I know to use the EXISTS only in the WHERE clause "I only want that rows where the following SELECT gives me something". This only makes sense if there is some connection between the one and the other table.

select id,foo from mydb y
where exists (select x.id from somedb x where x.id = y.id)
Jürgen Hollfelder
Right. This is kind of a gray area where I'm trying to mix procedure and structure in some unholy union, but the structure actually is "show me info, including whether or not the info passes some test".
Chris
Of course, the standby solution is to have two it in two steps: one with the test "if exists" in the where, and literally setting my flag to "1", and then doing it again with "if not exists", literally setting the flag to "0". Either into a temp table or I guess use a union...
Chris
@Chris: I am not sure now. Even if I look at the other SQL statement you added as a comment at the questions I am not sure why my SQL wouldn't solve problem. What is still needed? Like this:select t.foo, (case when 1=1 then '1' else '0' end) as lapsedFlag, (case when (select count(*) from x.bar cc where cc.foo = t.foo and cc.date_dt between '2010-05-01' (date) and '2010-07-31' (date) ) > 0 then '1' else '0' end) as MyFlag from x.bar
Jürgen Hollfelder
A: 

Since you're only interested in 1 and 0 as flag values, try the following:

select foo,
   coalesce((select max(1)
             from somedb x
             where x.bar > 0), 0) as MyFlag
from mydb
Mark Bannister
+2  A: 

I couldn't come up with a solution that was easy to read (key when you're dim-witted as I am), so I did a union into a temporary table:

create multiset table someDb.NiceFlags as
(
    select t.foo,
           '1' as myFlag
    from someDb.pos_txn_mstr t
    where exists(select x...)

  union all

    select t.foo,
           '0' as myFlag
    from someDb.pos_txn_mstr t
    where not exists(select x...)

) with data primary index(foo)

But now I don't feel like a tough guy :(

Chris
+1 I think the UNION ALL is a good workaround because the intention is clear and therefore easier to correct when this 'bug' gets fixed in a later version of Teradata (not sure why a temp table is needed, though)
onedaywhen