全外连接行为不端

时间:2013-10-09 18:11:31

标签: sql sql-server

我在同一个sql-server数据库中有两个表,它们连续两个季度存储应用程序名称和用户名(以及其他内容)。我想要的是一个完整的连接,它向表A中的用户显示不在表B中,反之亦然。

编辑: table_a和table_b都包含两个或多个记录,其中AppName和Username具有相同的值,因此需要DISTINCT。我编辑了下面的例子来反映这一点。

表-A:

-----------------------
| AppName  | Username |
-----------------------
| app1     | jdoe     |
| app1     | jsmith   |
| app1     | jdoe     |
| app2     | jsmith   |
-----------------------

表-B:

-----------------------
| AppName  | Username |
-----------------------
| app1     | fbar     |
| app1     | jsmith   |
| app1     | jboehner |
| app1     | fbar     |
| app3     | jboehner |
-----------------------

SQL:

SELECT DISTINCT a.username as q2, b.username as q3
FROM tablea as a
FULL JOIN tableb as b
ON a.username = b.username
WHERE a.appname = 'app1'
AND b.appname = 'app1'

预期结果:

-----------------------
| q2       | q3       |
-----------------------
| jdoe     |          |
| jsmith   | jsmith   |
|          | fbar     |
-----------------------
|          | jboehner |
-----------------------

实际结果:

-----------------------
| q2       | q3       |
-----------------------
| jsmith   | jsmith   |
-----------------------

是什么?

3 个答案:

答案 0 :(得分:4)

在OUTER JOINed表上使用WHERE子句(在这种情况下,两个表)都将其更改为INNER JOIN,因为过滤器应用于连接的结果,所有条件必须是满足。在您的情况下,除了匹配的行(它强制它为INNER JOIN)之外,这是不可能的。我怀疑这就是你的意思:

SELECT DISTINCT a.username as q2, b.username as q3
FROM dbo.tablea as a
FULL OUTER JOIN dbo.tableb as b
ON a.username = b.username
AND (a.appname = b.appname)
WHERE a.appname = 'app1' OR b.appname = 'app1';

-- or

SELECT DISTINCT a.username as q2, b.username as q3
FROM dbo.tablea as a
FULL OUTER JOIN dbo.tableb as b
ON a.username = b.username
AND (a.appname = b.appname)
WHERE 'app1' IN (a.appname, b.appname);

答案 1 :(得分:3)

SELECT  DISTINCT a.username as q2, b.username as q3
FROM    (SELECT x.* FROM tablea x WHERE x.appname = 'app1') as a
FULL JOIN (SELECT y.* FROM tableb y WHERE y.appname = 'app1') as b 
ON a.username = b.username

编辑#1:

USE AdventureWorks2008R2;
SET STATISTICS IO ON;
SET NOCOUNT ON;

PRINT 'Test #1 '
PRINT '{'
SELECT DISTINCT x.Name, y.Name
FROM
(
    SELECT  p.*
    FROM    Production.Product p
    WHERE   p.Name = 'HL Road Frame'
) x 
FULL OUTER JOIN
(
    SELECT  pm.*
    FROM    Production.ProductModel pm
    WHERE   pm.Name = 'HL Road Frame'
) y ON x.ProductModelID = y.ProductModelID
PRINT '}'
GO 

PRINT 'Test #2 '
PRINT '{'
SELECT DISTINCT p.Name, pm.Name
FROM Production.Product p
FULL OUTER JOIN Production.ProductModel pm
ON p.ProductModelID = pm.ProductModelID
AND (p.Name = pm.Name)
WHERE p.Name = 'HL Road Frame' OR pm.Name = 'HL Road Frame'
PRINT '}'
GO 

SET STATISTICS IO OFF;

编辑#2:

Test #1 
{
Table 'ProductModel'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
}
Test #2 
{
Table 'ProductModel'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Product'. Scan count 1, logical reads 15, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
}

编辑#3:

enter image description here

答案 2 :(得分:-3)

应该在哪里,或者不是: WHERE a.appname ='app1'或b.appname ='app1'