2012-02-23 148 views
3

我有一个查询,返回一个结果集,它看起来是这样的:TSQL:如何编写这个查询?

A | B 
--------------------- 
1 | a 
2 | a 
1 | b 
1 | c 
3 | d 

A|B是在结果唯一的(即有将永远只能是一个1|a行)

我需要写两个查询基于这些结果。第一:

赋予值A(比如1),算上B S上的号码谁只有一个单行;在A列中有1

所以在上述数据组,ID预期要返回的值2,因为Bbc只有每一个行中,其中那些行具有在A1d不会被计数,因为它对应于3而且a不会被返回,因为它有一个2的附加行。

希望是有道理的。

第二个查询与上面相反。

给定值A(比如1)计数的B小号谁拥有2个或更多的行,其中行已在A1数量。

所以在上面的数据ID期望返回1,因为B价值a是具有多行,用在A列1其中的一个唯一的一个。

感谢

回答

2

随着热膨胀系数和窗口聚合函数,这是可以做到这样的:

WITH 
    sampledata (A, B) AS (
    SELECT 1, 'a' UNION ALL 
    SELECT 2, 'a' UNION ALL 
    SELECT 1, 'b' UNION ALL 
    SELECT 1, 'c' UNION ALL 
    SELECT 3, 'd' 
), 
    counted AS (
    SELECT 
     A, 
     B, 
     COUNT(*) OVER (PARTITION BY B) B_count 
    FROM sampledata 
) 
SELECT 
    COUNT(*) 
FROM counted 
WHERE A = 1 
    AND B_count = 1 /* change to "> 1" to get the other result */ 
+0

这与Kirills的答案相比如何与效率相比?,我得到了一堆行(数千人) – 2012-02-23 11:09:20

+0

@Andrew,由于分组,它的性能扫描更差。 – 2012-02-23 11:10:45

+0

@AndrewBullock:我想是基里尔说的。半连接(以EXISTS谓词的形式)通常很难被打败,并且对于具有分组的查询(这意味着排序,这是昂贵的)更加困难。所以是的,如果你的桌子很大,我可能会用Kirill的解决方案。 – 2012-02-23 11:46:12

6

用途:

declare @t table(A int, B char(1)) 

insert @t values 
(1, 'a'), 
(2, 'a'), 
(1, 'b'), 
(1, 'c'), 
(3, 'd') 

declare @x int = 1 

select COUNT(*) 
from @t t 
where t.A = @x 
    and not exists(select 1 from @t t2 where t2.B = t.B and t2.A <> @x) 

select COUNT(*) 
from @t t 
where t.A = @x 
    and exists(select 1 from @t t2 where t2.B = t.B and t2.A <> @x) 

查询准确提供想要的结果:

----------- 
2  

----------- 
1 
+1

太棒了,谢谢 – 2012-02-23 10:47:22

+0

不客气。 – 2012-02-23 10:48:00