tags:

views:

139

answers:

6

I have a right outer join, that almost does what I want...

SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr

The problem is, I want to add a

where credit_acc.type_acc = 'init'

But this gets rid of all users who don't have a row in credit_acc... which is WHY I need a right outer join.

Is there a way to get this without having to do two queries and a union?

+4  A: 
SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr
WHERE credit_acc.type_acc = 'init' OR credit_acc.type_acc is NULL

Or, as @Tomalak pointed out:

WHERE COALESCE(credit_acc.type_acc, 'init') = 'init'

which may be faster (see comments).

Robert Gamble
Alternatively: WHERE COALESCE(credit_acc.type_acc, 'init') = 'init'
Tomalak
Good call - second the COALESCE optimization here.
Skeolan
@Tomalak, I wasn't very familiar with COALESCE but I looked it up and added it to the answer, thanks for teaching me something new.
Robert Gamble
Actually, adding Coalesce to the where clause will prevent the query from being sargable, therefore, any indexes that may exist on the type_acc column will not be used. If anything, using coalesce will slow down the query.
G Mastros
+1  A: 

Have you tried the following?

SELECT
users_usr.firstname_usr,
users_usr.lastname_usr,
credit_acc.given_credit_acc,
users_usr.created_usr,
users_usr.sitenum_usr,
users_usr.original_aff_usr,
users_usr.id_usr
FROM
credit_acc
right Outer Join users_usr ON credit_acc.uid_usr = users_usr.id_usr and credit_acc.type_acc = 'init'
Ben Noland
"and" doesn't work syntactically there. You haven't started a predicate clause yet. It should be "where". I assume the OP tried exactly this but, as he says, it filters out the desired rows where type_acc is NULL.
Dave Costa
+2  A: 

If the row doesn't exist, *credit_acc.type_acc* should be null. You could try something like this:

WHERE credit_acc.type_acc = 'init' OR credit_acc.type_acc IS NULL;

That will only work if there are no null fields in *credit_acc.type_acc*.

gpojd
A: 

You want all records from the two tables, joined on user-id, WHERE credit_acc is 'init' OR where there isn't a credit_acc row to be joined? How about

where credit_acc.type_acc is null  OR credit_acc.type_acc = 'init'
Skeolan
A: 

I would make the predicate:

WHERE credit_acc.uid_usr IS NULL OR credit_acc.type_acc = 'init'

This would give you rows where there is no match on UID_USR, and rows where there is a match and the account type is 'init'.

The other solution proposed (checking type_acc for NULL) would also give you rows where there is a match on UID_USR and the actual value for account type is NULL.

If credit_acc.type_acc can't be NULL, there's no difference between the two. If it can, you need to decide whether you want to include those rows in your result set.

Dave Costa
A: 

Just add another predicate to the Join Condition.

SELECT  U.firstname_usr, U.lastname_usr, C.given_credit_acc, 
        U.created_usr, U.sitenum_usr, U.original_aff_usr, U.id_usr
From credit_acc C Right Join users_usr U
   On C.uid_usr = U.id_usr
      And C.type_acc = 'init'

This works because Join conditions are applied BEFORE the non-matching records from "other" side of an "Outer" join are added to the result set, whereas Where Conditions are applied after the two tables are joined...

This syntax more clearly represents your intent as well...

Charles Bretana