下面我有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
答案 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
这是输出的图像。