选择包含给定数据集的不同行

时间:2011-07-19 10:34:45

标签: sql sql-server tsql

我有一张桌子:

bid | data
1   | a
1   | b
1   | c
2   | a
3   | c
3   | a

我想选择包含给定数据集的所有出价。

例如,所有出价都包含'数据“a”和“b”(结果应为出价1),或包含“a”和“c”(1和3)的出价。

只有我能想到的解决方案有点讨厌,所以我很感激一些帮助/建议。

我的第一次尝试:

select bid from my_table as t1 where 
exists (select * from my_table t2 where 
    t2.bid = t1.bid and 
    t2.data='a'
)
and
exists (select * from my_table t2 where 
    t2.bid = t1.bid and 
    t2.data='b'
)
group by bid;

感谢。

5 个答案:

答案 0 :(得分:5)

select t1.bid
from table_1 t1
inner join table_1 t2 on t1.bid = t2.bid
where t1.data = 'a' and t2.data = 'c'

顺便说一下:

  

所有“包含”数据“a”和“b”的出价(结果应为出价1)

- >出价2还包含数据'a'和'b'

答案 1 :(得分:3)

虽然我不建议仅针对两个变量查找使用此解决方案,但是当对更多变量进行匹配时,与每个匹配进行内部联接相比,查询成本增长率会增加非常缓慢。作为免责声明,我意识到如果管道是一个有效的字段,或者有xml编码的字符,这会破坏。

select e.bid
from myTable e
cross apply ( select '|'+ i.data + '|'
              from myTable i
              where e.bid = i.bid
              for xml path('')) T(v)
where v like '%|A|%' and v like '%|B|%' --and v like '%|C|%'.....
group by e.bid

作为一个与其他选项无关的方面,您的答案可以简化为

select bid from my_table as t1 where 
exists (select * from my_table t2 where 
    t2.bid = t1.bid and 
    t2.data='a'
)
and t1.data = 'c'
group by bid;

这大致相当于基督徒的答案。优化器很可能会对它们进行相同的处理。

 select distinct t1.bid
    from table_1 t1
    inner join table_1 t2 on t1.bid = t2.bid
    where t1.data = 'a' and t2.data = 'c'

答案 2 :(得分:1)

使用子查询,计算表中正确出现的次数。

SELECT DISTINCT m.bid
FROM myTable m
WHERE (
       SELECT COUNT(1) 
       FROM myTable m2
       WHERE    (m2.data = 'a' 
              OR m2.data = 'b')
       AND m.bid = m2.bid
      ) = 2

答案 3 :(得分:1)

使用exists

declare @t table(bid int, data char)

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

select distinct t1.bid
from @t t1
where exists(
    select 1
    from @t t2
    where t2.bid = t1.bid and t2.data = 'a'
)
    and exists(
    select 1
    from @t t2
    where t2.bid = t1.bid and t2.data = 'b'
)

XML PATH和XQuery版本:

select distinct t.bid
from
(
    select *
        , (
            select *
            from @t t2
            where t2.bid = t1.bid
            for xml path, root('root'), type
        ) [x]
    from @t t1
) t
where t.x.exist('root[*/data[text() = "a"] and */data[. = "b"]]') = 1

答案 4 :(得分:1)

也许不是最好的答案,但是:

select bid from mytable where data = 'a'
intersect
select bid from mytable where data = 'c'