Выберите отдельные строки, которые содержат данный набор данных - PullRequest
1 голос
/ 19 июля 2011

У меня есть следующая таблица:

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 ]

5 голосов
/ 19 июля 2011
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'

3 голосов
/ 19 июля 2011

Хотя я бы не рекомендовал это решение только для двух поисков переменных, темпы роста стоимости запросов при сопоставлении с большим количеством переменных увеличиваются очень медленно, а не при внутреннем соединении для каждого совпадения. Как заявление об отказе от ответственности, я понимаю, что, если труба является допустимым полем или есть кодированные в 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'
1 голос
/ 19 июля 2011

Возможно, не самый лучший ответ, но:

select bid from mytable where data = 'a'
intersect
select bid from mytable where data = 'c'
1 голос
/ 19 июля 2011

Использование 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 и версия 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
1 голос
/ 19 июля 2011

С помощью подзапроса подсчитайте количество правильных вхождений в вашей таблице.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...