0

Below I have sql select to retrieve values from a table. I want to retrieve the values from tableA regardless of whether or not there are matching rows in tableB. The below gives me both non-null values and null values. How do I filter out the null values if non-null rows exist, but otherwise keep the null values?

SELECT a.* FROM
(
    SELECT
            id,
            col1, 
            coll2
        FROM tableA a LEFT OUTER JOIN tableB b ON b.col1=a.col1 and b.col2='value'
        WHERE a.id= @id
          AND a.col2= @arg

) AS a

 ORDER BY col1 ASC 
1
  • You're missing a code segment. ) is missing it's friend. Commented Jan 24, 2014 at 19:42

3 Answers 3

1

You can do this by counting the number of matches using a window function. Then, either return all rows in A if there are no matching B rows, or only return the rows that do match:

select id, col1, col2
from (SELECT a.id, a.col1, a.coll2,
             count(b.id) over () as numbs
      FROM tableA a LEFT OUTER JOIN tableB b ON b.col1=a.col1 and b.col2='value'
      WHERE a.id = @id AND a.col2= @arg
     ) ab
where numbs = 0 or b.id is not null;
Sign up to request clarification or add additional context in comments.

Comments

1

Filter them out in WHERE clause

SELECT
    id,
    col1, 
    coll2
FROM tableA a LEFT OUTER JOIN tableB b ON b.col1=a.col1 and b.col2='value'
WHERE a.id= @id
  AND a.col2= @arg
  AND A.Col1 IS NOT NULL -- HERE
) AS a

ORDER BY col1 ASC 

Comments

0

For some reason, people write code like Marko that puts a filter (b.col2 = 'value') in the JOIN clause. While this works, it is not good practice.

Also, you should get in the habit of having the ON clause in the right sequence. We are joining table A to table B, why write it as B.col1 = A.col1 which is backwards.

While the above statement works, it could definitely be improved.

I created the following test tables.

-- Just playing
use tempdb;
go

-- Table A
if object_id('A') > 0 drop table A
go
create table A
(
  id1 int,
  col1 int,
  col2 varchar(16)
);
go

-- Add data
insert into A
values
(1, 1, 'Good data'),
(2, 2, 'Good data'),
(3, 3, 'Good data');

-- Table B
if object_id('B') > 0 drop table B
go
create table B
(
  id1 int,
  col1 int,
  col2 varchar(16)
);

-- Add data
insert into B
values
(1, 1, 'Good data'),
(2, 2, 'Good data'),
(3, NULL, 'Null data');

Here is the improved statement. I choose literals instead of variables. However, you can change for your example.

-- Filter non matching records
SELECT 
    A.*
FROM A LEFT OUTER JOIN B ON 
    A.col1 = B.col1 
WHERE 
    B.col1 IS NOT NULL AND
    A.id1 in (1, 2) AND
    A.col2 = 'Good data'
ORDER BY
    A.id1 DESC

Here is an image of the output.

enter image description here

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.