Требуется помощь при использовании JOIN для получения сумм или 0 из таблицы RIGHT, если запись отсутствует - PullRequest
0 голосов
/ 22 марта 2012

Мне нужно немного помочь со следующим запросом.Я уверен, что я обдумываю это, но здесь идет речь:

    SELECT 
        bc.name, 
        bc.category_id,
        bc.ref_id,
        COALESCE(bc.parent_id,bc.category_id) as parent_category_id,
        (select name FROM budget_categories bc2 WHERE bc2.category_id = bc.parent_id) as parent_name,
        (select ref_id FROM budget_categories bc2 WHERE bc2.category_id = bc.parent_id) as parent_ref_id, 
        COALESCE(sum(bee.amount),0) as amount
    FROM 
        budget_expected_expenses bee, budget_categories bc 
    WHERE 
        bc.group_id IN (1,139) AND
        bee.group_id = 1 AND
        bee.date BETWEEN '2012-01-01' AND '2012-01-31' AND 
        bee.cat_id = bc.category_id 
    GROUP BY bee.cat_id ORDER BY bc.ref_id ASC

По сути, цель состоит в том, чтобы вернуть сумму каждой категории в таблице «до н.- в данном случае 1 и 139 соответственно) из таблицы «пчела».Если в «пчеле» нет записи для конкретной группы, мне нужно, чтобы она возвращала 0. Однако этот запрос возвращает суммы только для значений, которые фактически имеют записи в таблице «пчела».Я уверен, что что-то мне не хватает, но, ну, я скучаю по этому.Заранее спасибо.

ПРИМЕЧАНИЕ: я пробовал разные JOINS, но ничего не работает.Очевидно, это возможно, я просто отключаюсь.

Ответы [ 3 ]

0 голосов
/ 22 марта 2012

Предложите переписать запрос, чтобы иметь левое соединение:

SELECT 
    ....
    COALESECE(SUM(bee.amount,0.00))
FROM
    budget_categories bc 
    LEFT JOIN
    budget_expected_expenses bee ON bee.cat_id = bc.category_id
WHERE 
    ...

LEFT JOIN всегда будет иметь как минимум одну запись результата для каждой записи в левой части объединения. В случае, если не было соответствующих правых записей, будет использоваться NULL, поэтому вам нужно COALESCE (), чтобы превратить это значение в 0,00.

0 голосов
/ 22 марта 2012

Я переписал с использованием более нового стиля ANSI, чем более старый формат списка таблиц, и явно добавил критерии объединения в предложении WHERE. Таким образом, вы должны лучше видеть взаимосвязь каждой таблицы с другими и явные ограничения (например, критерии даты), которые вы хотите применить к этим элементам JOINED. В предложении where остаются только критерии для первой таблицы выбора.

Я применил ДВА соединения к таблице категорий, однажды основываясь на вашем намерении найти категорию PARENT и имя и ссылочный идентификатор (при условии, что существует родительский идентификатор). Если нет, он будет искать найденный идентификатор категории по умолчанию.

Единственный сбой, который я думаю, я вижу, это объединение с ожидаемыми расходами, где ваши критерии только для group_ID = 1, а ваши критерии для категорий бюджета - либо 1, либо 139 (через в пункте). Если они фактически ПРЕДЛАГАЕТСЯ быть одинаковыми, то измените объединение на

"И bc.group_ID = bee.group_ID"

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

SELECT 
      bc.name, 
      bc.category_id,
      bc.ref_id,
      COALESCE( bc.parent_id,bc.category_id) as Which_Category_id,
      COALESCE( bcParent.Name, bcDefCat.Name ) as Category_Name,
      COALESCE( bcParent.Ref_ID, bcDefCat.Ref_ID ) as Category_Ref_ID,
      COALESCE(sum(bee.amount),0) as amount
    FROM 
        budget_categories bc 

           LEFT JOIN budget_expected_expenses bee
              ON bc.category_id = bee.cat_id
              AND bee.group_ID = 1
              AND bee.date BETWEEN '2012-01-01' AND '2012-01-31' 

           LEFT JOIN budget_categories bcParent
              on bc.parent_ID = bcParent.category_ID

           JOIN budget_categories bcDefCat
              on bc.Category_ID = bcDefCat.category_ID
   WHERE 
      bc.group_id IN (1,139) 
   GROUP BY 
      bc.category_id 
   ORDER BY 
      bc.ref_id ASC
0 голосов
/ 22 марта 2012
FROM budget_expected_expenses bee, budget_categories bc 

Если вы хотите, чтобы записи появлялись в bc, но не обязательно bee, выполните LEFT JOIN:

FROM budget_categories bc LEFT JOIN budget_expected_expenses bee ON bc.category_id = bee.cat_id

Вам также необходимо сгруппировать по столбцу, который гарантированне быть нулевым:

GROUP BY bc.category_id

Кроме того, ваш запрос намного сложнее, чем нужно, с перекрестным соединением и сложными подзапросами.Вы могли бы упростить это до что-то вроде этого:

SELECT 
    bc.name, 
    bc.category_id,
    bc.ref_id,
    COALESCE(bc.parent_id,bc.category_id) as parent_category_id,
    parent.name as parent_name,
    parent.ref_id as parent_ref_id, 
    COALESCE(sum(bee.amount),0) as amount
FROM 
    budget_categories bc
LEFT JOIN
    budget_expected_expenses bee ON bc.category_id = bee.cat_id
LEFT JOIN
    budget_categories parent ON bc.parent_id = parent.category_id
WHERE 
    bc.group_id IN (1,139) AND
    bee.group_id = 1 AND
    bee.date BETWEEN '2012-01-01' AND '2012-01-31'
GROUP BY bc.category_id ORDER BY bc.ref_id ASC
...