2010-07-26 4 views
3

Усталость мешает мне найти этот ... Скажем, у вас есть следующие таблицы:Select COUNT (*) или ноль

Родитель

  • PARENT_ID (LONG)

Ребенок

  • CHILD_ID (LONG)
  • PARENT_ID (LONG, FK)
  • HAS_GRADUATED (булево)

Я хочу, чтобы запрос, чтобы вернуть следующие истинный (1, в случае Oracle), если родитель имеет по крайней мере один ребенок, который закончил, и ложные (0, в случае, если Oracle), если родитель не ребенок, который закончил, или не имеет детей на всех:

PARENT_ID ................ HAS_CHILDREN_WHO_GRADUATED

5 .......................... ....... 1

3 ................................. 1

6 ................................ 0

2 ......... ........................ 0

В приведенном выше примере родительский элемент с parent_id = 5 может иметь> = 1 детей с градуировкой. То же самое является родителем с parent_id = 3. Родитель с parent_id = 6 либо вообще не имеет детей, либо имеет детей, но ни один из них не окончил.

Каким будет запрос к этому?

+1

Я полагаю, что таблица 'Child' также имеет внешний ключ' PARENT_ID'? – pascal

+0

Да, я уже редактировал, когда вы писали комментарий :-) –

ответ

0

Прежде всего, я не думаю, что вы можете использовать колонки LONG для этого, так как значения LONG не могут использоваться в WHERE условиях. Обратите внимание, что это верно с 10g, так как это то, что я использую.

Во-вторых, я предполагаю, что вы имеете в виду, что ваша дочерняя таблица должна иметь столбец PARENT_ID, иначе не было бы способа связывать две таблицы. Учитывая, что этот вопрос должен работать:

SELECT PARENT_ID, COUNT(1) FROM Child WHERE HAS_GRADUATED = 1 GROUP BY PARENT_ID 
+1

Это не будет список родителей без детей. – pascal

+0

Вы правы, моя ошибка исправит. – Dan

2

Будет ли это давать вам то, что вы ожидаете?

SELECT 
    P.Parent_Id, 
    CASE WHEN (SUM (CASE WHEN Has_Graduated = 1 then 1 else 0 END)) = 0 THEN 0 ELSE 1 as HAS_CHILDREN_WHO_GRADUATED 
FROM Parent P 
    LEFT JOIN Child C 
     ON P.Parent_Id = C.Parent_Id 
GROUP BY P.Parent_Id 
+0

Разве это не означает, сколько детей закончили для этого родителя? Он специально спросил 1 или 0. – WillfulWizard

+0

Чтобы быть более полезным, чем просто указывать на ошибку, мы могли бы просто внести это изменение: (1 <= Count (CASE WHEN Has_Graduated = 1 then 1 else 0))? – WillfulWizard

+1

ответ исправлен. –

7

Использование:

SELECT DISTINCT 
      p.parent_id, 
      CASE WHEN c.parent_id IS NULL THEN 0 ELSE 1 END 
    FROM PARENT p 
LEFT JOIN CHILD c ON c.parent_id = p.parent_id 
       AND c.has_graduated = 1 

Вы должны использовать внешнее соединение, чтобы увидеть родительские ценности, которые не имеют вспомогательные записи в дочерней таблице.

+0

DISTINCT должен работать лучше, чем группа. –

+0

@Philip Kelley: В Oracle - они выполняют то же самое. Мне пришлось бы копаться в статье AskTom об этом, потому что я думал так же, как и вы, и мой босс не был уверен =) –

+0

Спасибо за ответ (+1). На самом деле, я думаю, что это не сработает. Если у родителя есть дочерний объект, который имеет градиент, а другой, который не закончил, в конечном наборе результатов будет две строки. Один с parent_id и 1, а другой с parent_id и 0. –

0

Вот форма запроса, хотя синтаксис для Oracle может быть выключен:

SELECT 
    Parent.PARENT_ID 
    ,case count(Child.PARENT_ID) when 0 then 0 else 1 end HAS_CHILDREN_WHO_GRADUATED 
from Parent 
    left outer join Child 
    on Child.PARENT_ID = Parent.PARENT_ID 
where Child.HAS_GRADUATED = 1 
group by Parent.PARENT_ID 

Это будет список всех элементов Родитель один раз, с HAS_CHILDREN_WHO_GRADUATED набора 1 или 0 набора по желанию.

(Под ред добавить статью, где)

2

Вполне вероятно, что OMG Ponies решение будет работать лучше (именно поэтому он получил свою +1), но это еще один способ решения этой проблемы.

Select Parent_Id 
    , Case 
     When Exists(Select 1 
        From Child 
        Where Child.Parent_Id = Parent.Parent_Id 
         And Child.Has_Graduated = 1) Then 1 
     Else 0 
     End 
From Parent 
+0

+1 - ваш вариант работает (вариант @OMG Ponies возвращает неправильный результат). Производительность сомнительна, в некоторых вариантах ваш вариант работает быстрее – ThinkJet

+0

Упс ... потерял «c.has_graduated = 1» в ответ @OMG Ponies. Сожалею. Он тоже работает. – ThinkJet

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