2010-08-04 82 views
1

我有一个子选择在一个查询,看起来像这样:如何在不增加返回行数的情况下修改此查询?

left outer join 
    (select distinct ID from OTHER_TABLE) as MYJOIN 
on BASE_OBJECT.ID = MYJOIN.ID 

这是非常简单的。通过MYJOIN.ID在相关行中是否为空来检查查询的主对象与OTHER_TABLE表示的对象之间是否存在某种关系。

但是现在需求已经发生了一些变化。 OTHER_TABLE中的另一行可以具有1或0的值,并且查询需要知道1值的主要关系之间是否存在关系,以及它是否存在0值。最明显的解决方案是将:

left outer join 
    (select distinct ID, TYPE_VALUE from OTHER_TABLE) as MYJOIN 
on BASE_OBJECT.ID = MYJOIN.ID 

但是,因为如果0型和1型对象都存在相同的ID,这将增加通过查询,这ISN返回的行数,这将是错误的可以接受。因此,我需要的是某种子查询,它将为每个不同的ID返回1行,并带有“1类型存在”列和“0类型存在”列。我不知道如何在SQL中进行编码。

例如,下面的表中,

ID | TYPE_VALUE 
_________________ 
1 | 1 
3 | 0 
3 | 1 
4 | 0 

我想看到设置这样的结果:

ID | HAS_TYPE_0 | HAS_TYPE_1 
______________________________ 
1 | 0   | 1 
3 | 1   | 1 
4 | 1   | 0 

任何人都知道我怎么能建立一个查询做到这一点?希望至少有一些丑陋的黑客?

回答

3

在一般情况下,你可以使用EXISTS:

SELECT DISTINCT ID, 
    CASE WHEN EXISTS (
      SELECT * FROM Table1 y 
      WHERE y.TYPE_VALUE = 0 AND ID = x.ID) 
     THEN 1 
     ELSE 0 END AS HAS_TYPE_0, 
    CASE WHEN EXISTS (
      SELECT * FROM Table1 y 
      WHERE y.TYPE_VALUE = 1 AND ID = x.ID) 
     THEN 1 
     ELSE 0 END AS HAS_TYPE_1 
FROM Table1 x; 

如果你有一个非常大的数字表中的元素,这将不会进行如此之大 - 这些嵌套子查询的往往是一个吻当涉及到表演的时候,他会死。

针对您的特殊情况下,你也可以使用GROUP BY和MAX()和MIN(),以加快速度:

SELECT 
    ID, 
    CASE WHEN MIN(TYPE_VALUE) = 0 THEN '1' ELSE 0 END AS HAS_TYPE_0, 
    CASE WHEN MAX(TYPE_VALUE) = 1 THEN '1' ELSE 0 END AS HAS_TYPE_1 
FROM Table1 
GROUP BY ID; 
+0

谢谢! GROUP BY运作良好。是的,这可能是一个包含数十或数十万个元素的非常大的数据集。 – 2010-08-04 21:59:57

2

代替select distinct ID, TYPE_VALUE from OTHER_TABLE 使用

select ID, 
MAX(CASE WHEN TYPE_VALUE =0 THEN 1 END) as has_type_0, 
MAX(CASE WHEN TYPE_VALUE =1 THEN 1 END) as has_type_1 
from OTHER_TABLE 
GROUP BY ID; 

你可以做同样使用PIVOT操作者...

相关问题