2017-08-31 225 views
1

我正在编写一个存储过程来填充多选控件,我想从数据库表中取回至少100个选项,但我想确保将所有选项都带回用户已经选定。使用UNION出现意外的结果

现有的查询带回只有第100行:

SELECT TOP 100 
    t2.Id, 
    t2.value2 
FROM 
    table1 t1 
INNER JOIN 
    table2 t2 
    ON 
    t1.clientId = t2.clientId AND t1.Id = t2.Id 
WHERE 
    t1.clientId = 1 

我添加了一个UNION到这个查询,以确保我总是选定的选项后面还有:

SELECT TOP 100 
     t2.Id, 
     t2.value2 
    FROM 
     table1 t1 
INNER JOIN 
     table2 t2 ON 
     t1.clientId = t2.clientId AND t1.Id = t2.Id 
WHERE 
     t1.clientId = 1 
UNION 
SELECT t2.id, 
     t_si.externalCertificateNumber 
    FROM table2 t2 
INNER JOIN 
     Table3 t3 
    ON t2.value = 333 

在我的一个测试例子中,有4个先前选择的选项。其中3个将返回前100名(1不是,因此需要更新)。

我预计会回到101行,并惊讶地得到104.我认为这是固有的DISTINCT正在工作的方式。

但是我也看到的是返回的不同的结果。随着一些(超过3个)不同的值出现。还有一些在之前的TOP 100中没有了!

所以我的问题是,UNION有某种内置的排序,会影响结果?或者还有其他事情在这里发生?

-----------------------------编辑---------------- --------------

如果我改变上述查询前5:

和先前选择的值是:

1, Blue 
2, Green 
20, Violet 
100 Indigo 

的结果SELECT自己看起来像这样:

1, Blue 
2, Green 
7, Red 
15, Cyan 
20, Violet 

为SELECT和UNION结果

1, Blue 
2, Green 
33, Cyan 
20, Violet 
24, Yellow 
100, Indigo 
60, Aero 
40, Amber 
25, Black 

这是由例如从数据库中没有,但要注意,红色在SELECT从SELECT与UNION

+0

? – jarlh

+0

我的猜测是,您的查询中的第二个选择返回多个记录。你为什么期望从该查询中获得单个记录? –

+0

@jarlh它返回4,这是我的预期。这是之前选择的4个选项。 – AidanO

回答

2

我开始怀疑,加上UNION改变了 执行计划,并且由于没有为了明确设置,这 是影响什么的回来。

你是对的。

TOP 100没有ORDER BY返回一些 100行。没有定义返回哪些行。

没有UNION的查询的第一个版本返回了一组100行,第二个版本的查询UNION返回了另一组100行。

要获得可预测和预期的结果,您应该在使用TOP的查询中添加ORDER BY。理想情况下,排序应该是明确的。

是的,UNION确实具有“内置”排序。如果你看执行计划,你通常会看到它。

我更喜欢使用共表表达式(CTE)来编写复杂的查询,像这样的:如果你运行第二个选择独立的,有多少行返回

WITH 
CTE 
AS 
(
    SELECT TOP 100 
     t2.Id, 
     t2.value2 
    FROM 
     table1 t1 
     INNER JOIN table2 t2 
      ON t1.clientId = t2.clientId 
      AND t1.Id = t2.Id 
    WHERE 
     t1.clientId = 1 
    ORDER BY 
     t2.Id 
) 
SELECT 
    Id, 
    value2 
FROM 
    CTE 

UNION 

SELECT 
    t2.id, 
    t_si.externalCertificateNumber 
FROM 
    table2 t2 
    INNER JOIN Table3 t3 ON t2.value = 333 
; 
2

UNION操作员移开失踪重复记录。要保留所有记录使用UNION ALL

SELECT TOP 100 
    t2.Id, 
    t2.value2 
FROM 
    table1 t1 
    INNER JOIN 
    table2 t2 ON 
     t1.clientId = t2.clientId AND 
     t1.Id = t2.Id 
WHERE 
    t1.clientId = 1 
UNION ALL 
SELECT t2.id, t_si.externalCertificateNumber FROM table2 t2 
    INNER JOIN Table3 t3 
    ON t2.value = 333 

TOP 100查询缺失的记录很容易被UNION也是结果集中的不同数量的记录来解释,和。

+0

我同意UNION解释不同数量的记录,但不是不同的结果。我开始怀疑添加UNION已经改变了执行计划,并且因为没有明确设置的顺序,所以这影响了回来的事情。 – AidanO

+0

执行计划与结果集应该没有任何关系,只有得到这些结果的速度有多快。第二个查询实际返回多少条记录? –

+0

104个结果,当有4个先前选择的选项时 – AidanO