2012-09-26 31 views
3

我收到来自针对Micrsoft SQL Server 2008(10.0.1600.22/Service Pack 2)的查询的意外结果。查询忽略WHERE子句中的过滤

它可能是一个错误?

我试图创建一个类似的查询来复制问题 - 没有成功。所以我猜这个查询本身没有问题,但其他的东西却导致了这种奇怪的行为。

我希望对可能导致问题的一些建议。

首先,来看看这个工作例如:

DROP TABLE #TempType 
DROP TABLE #TempData 

SELECT * INTO #TempType FROM (
    SELECT 1 AS Id, 10 AS TempDataFK, 'Do' AS Name, 'CODE1' AS Type UNION 
    SELECT 2 AS Id, 10 AS TempDataFK, 'Re' AS Name, 'CODE2' AS Type UNION 
    SELECT 3 AS Id, 20 AS TempDataFK, 'Mi' AS Name, 'CODE2' AS Type UNION 
    SELECT 5 AS Id, 10 AS TempDataFK, 'Fa' AS Name, 'CODE3' AS Type UNION 
    SELECT 6 AS Id, 20 AS TempDataFK, 'So' AS Name, 'CODE4' AS Type 
) sub 

SELECT * INTO #TempData FROM (
    SELECT 10 AS Id, 150 AS Number UNION 
    SELECT 20 AS Id, 150 AS Number UNION 
    SELECT 30 AS Id, 150 AS Number UNION 
    SELECT 40 AS Id, 180 AS Number 
) sub 

SELECT C1.Name Name1, 
     C2.Name Name2, 
     C3.Name Name3, 
     C4.Name Name4, 
     #TempData.Id, 
     #TempData.Number 
FROM #TempData 
    LEFT JOIN #TempType C1 (NOLOCK) 
     ON #TempData.Id = C1.TempDataFK 
     AND C1.Type = 'CODE1' 
    LEFT JOIN #TempType C2 (NOLOCK) 
     ON #TempData.Id = C2.TempDataFK 
     AND C2.Type = 'CODE2' 
    LEFT JOIN #TempType C3 (NOLOCK) 
     ON #TempData.Id = C3.TempDataFK 
     AND C3.Type = 'CODE3' 
    LEFT JOIN #TempType C4 (NOLOCK) 
     ON #TempData.Id = C4.TempDataFK 
     AND C4.Type = 'CODE4' 
WHERE 1=1 
    AND (#TempData.Number = 150) 
    AND (C1.Name='Mi' OR C2.Name='Mi' OR C3.Name='Mi' OR C4.Name='Mi') 

正如你可以看到我左侧的接合部表TempTypeTempData四倍。每次给它一个不同的别名。然后我过滤一定数量(150),并希望至少有一个名称应该是'Mi'。

结果不出所料:

-------------------------------------------- 
Name1 Name2 Name3 Name4 Id Number 
NULL Mi  NULL So  20 150 
-------------------------------------------- 

不过,如果我运行一个类似的查询对我的客户数据库中,我得到:

-------------------------------------------- 
Name1 Name2 Name3 Name4 Id Number 
Do  Re  Fa  NULL 10 150 
NULL Mi  NULL So  20 150 
NULL NULL NULL NULL 30 150 
-------------------------------------------- 

这是因为如果类似(C1.Name='Mi' OR C2.Name='Mi' OR C3.Name='Mi' OR C4.Name='Mi')的一部分,不使用在过滤中。

不同的查询,但相同的结构
在客户数据库中的表是不是暂时的,它们已经包含数据。桌子也有其他各种各样的领域,但我仍然只剩下一张桌子。所以结构与上面相同。

无法在新的数据库复制
我试图只用表和受影响的字段创建一个新的数据库复制的问题 - 在复制的问题没有更迭。

模式
值得一提的是客户数据库包含几个模式。两个类似于TempData和TempType的表都属于同一个模式(不是dbo)。 此外,与TempType.Type类似的字段是另一个模式中另一个表的外键,但由于我们没有加入,所以我没有看到它是相关的?

另一个特点
如果我把C1.Name等,为我的选择的一部分,就像这样:

SELECT C1.Name Name1, 
     C2.Name Name2, 
     C3.Name Name3, 
     C4.Name Name4, 
     #TempData.Id, 
     #TempData.Number, 
     CASE WHEN (C1.Name = 'Mi' AND C1.Name IS NOT NULL) THEN 1 ELSE 0 END, 
     CASE WHEN (C2.Name = 'Mi' AND C2.Name IS NOT NULL) THEN 1 ELSE 0 END, 
     CASE WHEN (C3.Name = 'Mi' AND C3.Name IS NOT NULL) THEN 1 ELSE 0 END, 
     CASE WHEN (C4.Name = 'Mi' AND C4.Name IS NOT NULL) THEN 1 ELSE 0 END 

我得到对我的客户数据库中所预期的结果(只有一行):

Name1 Name2 Name3 Name4 Id Number (No column name) (No column name) (No column name) (No column name) 
NULL Mi  NULL So  20 150  0     1     0     0 


任何建议,这可能是导致此?

+0

你说你正在运行一个不同的查询。你能告诉我们那个查询吗?如果该查询使用相同的地方,那么()可能是Or中和AND中的优先问题。另外,为什么1 = 1在哪里? –

+2

不是说这可以解决问题,但请注意'LEFT JOIN a ... WHERE a.something = something'将其变成了'INNER JOIN'。您可能需要将C1上的“过滤器”移动到联接的ON子句中,而不是查询的过滤器子句。 –

+0

@ElVieejo我无法显示原始查询(因为它包含特定于客户端的字段名称),但结构是100%相似的。也是括号。 1 = 1只是为了更容易的调试(注释掉例如“AND(#TempData.Number = 150)”) –

回答