2012-02-07 3 views
5

Трудно правильно установить, но я использую MySQL, и мне нужно выбрать один идентификатор, назовем его parent_id, который должен соответствовать значениям child_id в нескольких строках.Выбор идентификатора, который удовлетворяет нескольким статьям

Например:

+-----------+----------+ 
    | parent_id | child_id | 
    +-----------+----------+ 
    |  1  | 10 | 
    +-----------+----------+ 
    |  2  | 11 | 
    +-----------+----------+ 
    |  2  | 12 | 
    +-----------+----------+ 
    |  3  | 13 | 
    +-----------+----------+ 
    |  4  | 11 | 
    +-----------+----------+ 
    |  5  | 12 | 
    +-----------+----------+ 

Теперь, если я прохожу child_id параметры 11 и 12, я должен получить parent_id 2 назад, но если я прохожу 10 и 11, я не получить ничего взамен. Кроме того, если я прохожу 11, я должен получить 4. И если я прохожу 13, я должен получить 3 обратно.

Как это сделать? Я пробовал подсчитывать parent_id и использовать предложение HAVING, также используя предложение GROUP BY, но ничего не пытаюсь удовлетворить всем моим требованиям.

РЕДАКТИРОВАТЬ:

Пример Фидл: http://sqlfiddle.com/#!2/abbc4/5

EDIT2:

Ожидаемые результаты:

Передаваемые параметры: 11, 12 Полученный результат: 2

Передаваемые параметры: 11 Полученный результат: 4

Передаваемые параметры: 13 Полученный результат: 3

Передаваемые параметры: 12, 13 Полученный результат NULL

EDIT3:

Обновлена ​​спецификация. См. Также: http://sqlfiddle.com/#!2/2f750/1

+0

Wow! Даже перевод Google не мог помочь мне понять это. –

+3

Это не вина ОП. Это вполне понятно: он хочет создать запрос, который возвращает 'parent_id', только если были указаны все соответствующие' child_id 'и не указано' child_id', которое принадлежит другому 'parent_id' –

+0

. Что вы получите за '10, 13'. Ничего? Или '1' и' 3'? Альтернативно: для '11, 12, 13': Ничего? Или '2' и' 3'? –

ответ

2

Следующее заявление делает то, что вы хотите. Я не уверен, что о его исполнении, хотя ...

select t.parent_id, t.cnt from 
(
    select parent_id, count(*) cnt 
    from t 
    WHERE child_id IN (12, 11) 
    GROUP BY parent_id 
) t 
inner join 
(
    select parent_id, count(*) cnt 
    from t group by parent_id 
) s 
on t.parent_id = s.parent_id 
and t.cnt = s.cnt -- Check that the parent has exactly as many children as 
        -- passed in - and not more. Prevents matching if only part 
        -- of the children of a parent were specified. 
and t.cnt = 2 -- Check that all passed in children produced a match on the same 
       -- parent. Prevents matching of parents that match only a subset 
       -- of the specified children 

Заменить 2 с количеством указанных детей в IN списке.

+0

+1 полностью соответствует спецификации обновления. – dgw

+0

@dgw: Спасибо, но это была спецификация с самого начала. –

+0

Вы сделали чудеса здесь. К сожалению, я не полностью написал спецификацию. Я собираюсь обновить вопрос с полной hoorah. – donkapone

0

Для этого необходимо иметь две переменные. Первый - это список ваших дочерних_кодов (child_list), а второй - число детей (количество детей в вашем списке child_list), которое вы ищете (child_count).

SELECT parent_id,COUNT(*) 
FROM table 
WHERE child_id IN (<child_list>) 
GROUP BY parent_id 
HAVING COUNT(*)=<child_count> 

Это должно дать вам желаемые результаты.

+0

Мне нравится элегантность вашего ответа. Однако разве это не работает, если вы уже знаете, какого родителя вы ищете и, следовательно, имеете число своих детей? –

+0

@ DanielHilgarth Если я правильно понял OP, его вопрос был «У меня есть дети x, y, z и хочу знать, все ли они связаны с общим родителем». И тогда вы узнаете число детей. – dgw

+0

OP четко заявляет в своем ответе, что он хочет, чтобы соответствующий родитель возвращал значение. Таким образом, родитель - это ожидаемый результат, а не часть ввода. –

1

Вы также можете использовать эту более компактную версию

select case 
     when min(t.parent_id) = max(t.parent_id) -- parent_ids are the same? 
       -- and all children share the same parent? 
       and count(t.parent_id) = (
          select count(parents.parent_id) 
          from t parents 
          where parents.parent_id in 
           (select parent_id 
           from t 
           where child_id in (11, 12) -- <= change here 
           )) 
     then t.parent_id 
     else null 
     end as parent_id 
    from t 
where child_id in (11, 12); -- <= and here 

Я испытал это и работает для всех случаев использования

Вы можете проверить здесь http://sqlfiddle.com/#!2/abbc4/183

Смежные вопросы