2009-12-18 4 views
1

У меня есть быстрый вопрос о состоянии оператора select.SQL Выберите условие Вопрос

У меня есть следующая таблица со следующими элементами. Мне нужно получить идентификатор объекта, который соответствует идентификаторам типа.

TypeId ObjectId 
1  10 
2  10 
1  11 

Так что мне нужно, чтобы получить как объект 10, так как он соответствует идентификатору типа 1 и 2.

SELECT ObjectId 
FROM Table 
WHERE TypeId = 1 
AND TypeId = 2 

Очевидно, что это не работает, потому что он не будет соответствовать обоим условиям для одной и той же строки. Как выполнить этот запрос? Также обратите внимание, что я могу передать 2 или более идентификаторов типа, чтобы сузить результаты.

+0

должен заметить, что в запросе не будет всего 2 идентификатора типа. Это часть большего запроса, и количество пройденных идентификаторов типа будет равно 2 или более. Я бы подумал, что было бы проще решить эту проблему, поскольку таблицы сопоставления распространены в базах данных. – Josh

+0

Укажите полную проблему с ожидаемыми входами и поведением. Если в запросе три, и он должен соответствовать всем трем или что? –

+0

Как вы передаете идентификаторы запроса? Единая запятая или таблица? –

ответ

1

Этот код написан на основе Oracle. Она должна быть достаточно общее для других разновидностей SQL

select t1.ObjectId from Table t1 
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId 
where t1.TypeId = 1; 

Чтобы добавить дополнительные TypeIds, вы просто должны добавить еще присоединиться:

select t1.ObjectId from Table t1 
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId 
join Table t3 on t3.TypeId = 3 and t1.ObjectId = t3.ObjectId 
join Table t4 on t4.TypeId = 4 and t1.ObjectId = t4.ObjectId 
where t1.TypeId = 1; 

Важное примечание: при добавлении более соединений, производительность будет страдать МНОГО.

Что касается ответа Билла вы можете изменить его на следующее, чтобы избавиться от необходимости считать уникальность:

SELECT ObjectId 
FROM (SELECT distinct ObjectId, TypeId from Table) 
WHERE TypeId IN (1, 2) 
GROUP BY ObjectId 
HAVING COUNT(*) = 2; 

Его способ сделать это лучше масштабируется, как число типов становится больше.

+0

Вам понадобится префикс ObjectId –

+0

Да, я понял, что после его опубликования. Я отредактировал это и исправил предложение о сломанном соединении. –

5

автообъединение:

SELECT t1.ObjectId 
FROM Table AS t1 
INNER JOIN Table AS t2 
    ON t1.ObjectId = t2.ObjectId 
    AND t1.TypeId = 1 
    AND t2.TypeId = 2 

Примечание уверены, как вы хотите, чтобы поведение работать при переходе в значениях, но это начало.

+0

Что мне делать, если мне нужно добавить к запросу еще один идентификатор типа? – Josh

+0

'Добавить другой тип id' Вам нужно сопоставить все три или только два из трех? –

+0

Он должен соответствовать всем идентификаторам типа. Поэтому, если я хочу фильтровать на 2, я получу идентификатор объекта, который соответствует идентификаторам типа. Если я хочу отфильтровать по 3 идентификаторам типа, я получу идентификатор объекта, соответствующий всем 3 идентификаторам типа. – Josh

3

Я поддержал ответ от @Cade Roux, и вот как я это сделаю.

Но FWIW, вот альтернативное решение:

SELECT ObjectId 
FROM Table 
WHERE TypeId IN (1, 2) 
GROUP BY ObjectId 
HAVING COUNT(*) = 2; 

Предполагая, что уникальность над TypeId, ObjectId.


Re комментарий от @Josh, что он, возможно, придется искать в течение трех или более TypeId значений:

Решение с использованием JOIN требует объединения на значение, которое вы ищете. Решение выше с использованием GROUP BY может быть проще, если вы обнаружите, что ищете все большее число значений.

+0

Это не удастся, если он когда-либо находится в их с тем же TypeId более одного раза. –

+0

@David: Правильно, поэтому я заметил, что я предполагаю уникальность над TypeId, ObjectId. –

+1

Это может быть предпочтительнее моего ответа (для обслуживания и производительности) с требованиями к спискам переменных (конечно, план выполнения проверки), но также будет терпеть неудачу в случае 3 совпадений. Я считаю, что потребность в изменяющемся входе должна быть лучше определена, чтобы понять подходящее окончательное решение. –

0

Попробуйте

Пример ввода: (случай 1)

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all  
    select 1,11 
select * from @t 

Пример ввода: (Случай 2)

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all 
    select 3,10 union all select 4,10 union all 
    select 5,10 union all select 6,10 union all 
    select 1,11 union all select 2,11 union all 
    select 3,11 union all select 4,11 union all 
    select 5,11 union all select 1,12 union all 
    select 2,12 union all select 3,12 union all 
    select 4,12 union all select 5,12 union all 
    select 6,12 
select * from @t 

Пример ввода: (случай 3) [Дублированные записи есть]

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all 
    select 1,10 union all select 2,10 union all 
    select 3,10 union all select 4,10 union all 
    select 5,10 union all select 6,10 union all 
    select 1,11 union all select 2,11 union all 
    select 3,11 union all select 4,11 union all 
    select 5,11 union all select 1,12 union all 
    select 2,12 union all select 3,12 union all 
    select 4,12 union all select 5,12 union all 
    select 6,12 union all select 3,12 

В случае 1, выходной сигнал должен быть 10

В случае 2 & 3, выходной сигнал должен быть 10 и 12

Запрос:

select X.ObjectId from 
(
select 
      T.ObjectId 
      ,count(ObjectId) cnt 
from(select distinct ObjectId,Typeid from @t)T 
where T.Typeid in(select Typeid from @t) 
group by T.ObjectId)X 
join (select max(Typeid) maxcnt from @t)Y 
on X.cnt = Y.maxcnt 
Смежные вопросы