【问题标题】:both FULL OUTER JOIN and WHERE to get true result?FULL OUTER JOIN 和 WHERE 获得真正的结果?
【发布时间】:2011-08-18 12:11:58
【问题描述】:

我写了这个脚本。如果我们在 WHERE 子句中注释这两个部分,则结果中会忽略某些行。谁能告诉我为什么?

在第一个查询中,它作为 FULL OUTER JOIN 工作,但在第二个查询中,查询结果为 INNER JOIN 并且只返回一行,尽管使用了 UNKNOWN 条件解析的 WHERE 子句。

DECLARE @ALLDATA TABLE 
( 
[Id]        INT,
[T3Id]      INT,
[StockId]   INT,
[Serial]    INT,
[ISDel]     INT
)
INSERT INTO @ALLDATA ([Id],[T3Id],[StockId],[Serial],[ISDel])
Select 5 AS [Id],11 AS [T3Id],5 AS [StockId],0 AS [Serial],1 AS [ISDel]
UNION ALL
Select 1 AS [Id],11 AS [T3Id],5 AS [StockId],0 AS [Serial],1 AS [ISDel]
UNION ALL
Select 1 AS [Id],11 AS [T3Id],5 AS [StockId],1 AS [Serial],-1 AS [ISDel]
UNION ALL
Select 2 AS [Id],11 AS [T3Id],5 AS [StockId],2 AS [Serial],-1 AS [ISDel]
UNION ALL
Select 3 AS [Id],11 AS [T3Id],5 AS [StockId],3 AS [Serial],-1 AS [ISDel]
UNION ALL
Select 4 AS [Id],11 AS [T3Id],5 AS [StockId],4 AS [Serial],-1 AS [ISDel]

SELECT 'WITH CONDITIONS:'

SELECT 
 ISNULL(DataIns.[Id],DataDEL.[Id])      AS [Id]
,ISNULL(DataDEL.[StockId],-1)           AS [OLDStockId]
,ISNULL(DataDEL.[Serial],0)             AS [OLDSerial]
,ISNULL(DataIns.[StockId],-1)           AS [NEWStockId]
,ISNULL(DataIns.[Serial],0)             AS [NEWSerial]
,ISNULL(DataIns.[T3Id],DataDEL.[T3Id])  AS [T3Id]
,DataIns.[ISDel]                        AS [ISDel1]
,DataDEL.[ISDel]                        AS [ISDel2]
FROM @ALLDATA       AS DataIns
FULL OUTER JOIN @ALLDATA AS DataDEL 
ON 
DataDEL.Id = DataIns.Id 
AND  
DataDEL.ISDel = 1 
AND 
DataIns.ISDel = -1
WHERE ISNULL(DataDEL.[ISDel],1) = 1 AND ISNULL(DataIns.[ISDel],-1) = -1 

SELECT 'WITHOUT CONDITIONS:'

SELECT 
 ISNULL(DataIns.[Id],DataDEL.[Id])      AS [Id]
,ISNULL(DataDEL.[StockId],-1)           AS [OLDStockId]
,ISNULL(DataDEL.[Serial],0)             AS [OLDSerial]
,ISNULL(DataIns.[StockId],-1)           AS [NEWStockId]
,ISNULL(DataIns.[Serial],0)             AS [NEWSerial]
,ISNULL(DataIns.[T3Id],DataDEL.[T3Id])  AS [T3Id]
,DataIns.[ISDel]                        AS [ISDel1]
,DataDEL.[ISDel]                        AS [ISDel2]
FROM @ALLDATA       AS DataIns
FULL OUTER JOIN @ALLDATA AS DataDEL 
ON 
DataDEL.Id = DataIns.Id 
--AND 
--  DataDEL.ISDel = 1 
--AND 
--  DataIns.ISDel = -1
WHERE ISNULL(DataDEL.[ISDel],1) = 1 AND ISNULL(DataIns.[ISDel],-1) = -1 

期望的输出:

1    5  0    5  1   11    -1       1
2   -1  0    5  2   11    -1    NULL
3   -1  0    5  3   11    -1    NULL
4   -1  0    5  4   11    -1    NULL
5    5  0   -1  0   11  NULL       1

【问题讨论】:

  • 请显示实际样本输出。不要让我们运行你的代码。

标签: sql-server tsql


【解决方案1】:

谁能告诉我为什么?

因为这是FULL OUTER JOIN 的工作方式。

当您注释掉ON 子句中的附加条件时,实际上您得到的是INNER JOIN(因为id 在自联接中总是会产生至少一个匹配项)。

您的第一个查询对我来说也没有意义(或者您有一些非常复杂的要求)。

我相信你想要这个:

SELECT   ISNULL(DataIns.[Id],DataDEL.[Id])      AS [Id]
        ,ISNULL(DataDEL.[StockId],-1)           AS [OLDStockId]
        ,ISNULL(DataDEL.[Serial],0)             AS [OLDSerial]
        ,ISNULL(DataIns.[StockId],-1)           AS [NEWStockId]
        ,ISNULL(DataIns.[Serial],0)             AS [NEWSerial]
        ,ISNULL(DataIns.[T3Id],DataDEL.[T3Id])  AS [T3Id]
        ,DataIns.[ISDel]                        AS [ISDel1]
        ,DataDEL.[ISDel]                        AS [ISDel2]
FROM    (
        SELECT  *
        FROM    @alldata
        WHERE   isdel = 1
        ) dataDel
FULL JOIN
        (
        SELECT  *
        FROM    @alldata
        WHERE   isdel = -1
        ) dataIns
ON      dataDel.id = dataIns.id

【讨论】:

  • 感谢 Quassnoi,但事实并非如此。我想让 SQL 做 FULL OUTER JOIN,但我还必须在 WHERE 中添加一些额外的表达式,我不知道为什么。
  • @aporia: 你能发布你想要得到的结果集吗?
  • 我在帖子末尾添加了我的预期输出。这是第一个查询的结果。我认为最后一个查询也必须在逻辑上返回。
  • @aporia:我的查询准确地返回了你想要的(并且比你的第一个更有效)。您的最后一个查询是自加入 id。既然是自加入,总会有一个匹配:无论你在左侧取哪个id,在右侧总是至少有一个相同的id(来自同一条记录),反之亦然,所以实际上是INNER JOIN。这也意味着isDel 永远不能是NULL,也永远不能同时等于1-1,所以相同记录上的匹配总是会被过滤掉。只需在最后一个查询中注释掉WHERE 条件即可查看。
猜你喜欢
  • 2019-08-07
  • 2013-03-10
  • 1970-01-01
  • 2018-02-28
  • 2012-02-13
  • 2010-11-15
  • 1970-01-01
  • 2011-03-14
  • 2011-09-28
相关资源
最近更新 更多