仅当SQL select中存在空值时才过滤掉空值

时间:2014-01-24 19:39:40

标签: sql sql-server sql-server-2008

下面我有sql选择从表中检索值。我想从tableA中检索值,无论tableB中是否有匹配的行。下面给出了非空值和空值。如果存在非空行,如何过滤掉空值,否则保留空值?

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 

3 个答案:

答案 0 :(得分:1)

在WHERE子句

中过滤掉它们
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 

答案 1 :(得分:1)

您可以通过使用窗口函数计算匹配数来完成此操作。然后,如果没有匹配的A行,则返回B中的所有行,或者仅返回匹配的行:

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;

答案 2 :(得分:0)

出于某种原因,人们编写像Marko这样的代码,在JOIN子句中放置一个过滤器(b.col2 ='value')。虽然这有效,但这不是一种好的做法。

另外,你应该养成以正确的顺序使用ON子句的习惯。我们将表A加到表B,为什么把它写成B.col1 = A.col1,它是向后的。

虽然上述说法有效,但肯定可以改进。

我创建了以下测试表。

-- 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');

这是改进的陈述。我选择文字而不是变量。但是,您可以更改示例。

-- 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

这是输出的图像。

enter image description here