MySQL JOIN помощь - PullRequest
       4

MySQL JOIN помощь

1 голос
/ 25 июля 2011

Я боролся с этим запросом уже несколько дней. Я использую PHP / MySQL.

Это система, в которой клиенты могут отправлять грузы для сбора или доставки компанией, для которой я разрабатываю. Запрос, который я пытаюсь написать, соберет сборы и поставки, выполненные для клиента, и отправит им сводку того, что они потратили в тот день.

У меня есть два набора результатов ниже, которые мне нужно "объединить", чтобы отправить отчет.

(Не беспокойтесь о специфике, проблема заключается в объединении :))

Набор результатов поставок

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

summary_day, num_cons, num_spaces, customer_code 
2011-07-20      1       3           COB001P
2011-07-20      1       3           FAI001P
2011-07-20      2       2           FRE001P
2011-07-20      2       2           MIN001P
2011-07-20      17      29          NOR001P
2011-07-20      50      79          PAL001P
2011-07-20      1       1           PAR001P
2011-07-20      1       1           POT002P
2011-07-20      6       7           RHY001P
2011-07-20      9       13          TDG001P
2011-07-20      18      23          UPN001P

Набор результатов коллекций

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

2011-07-20  9   15  ARR001P
2011-07-20  1   1   BAC002P
2011-07-20  1   1   BLA001P
2011-07-20  4   6   CAR003P
2011-07-20  2   2   DIS001P
2011-07-20  2   2   DOV001P
2011-07-20  1   1   DRY001P
2011-07-20  1   1   ECC001P
2011-07-20  3   5   FAI001P
2011-07-20  2   2   INV001P
2011-07-20  2   2   MIN001P
2011-07-20  3   3   PAL001P
2011-07-20  1   1   QUA002P
2011-07-20  1   1   TEC002P
2011-07-20  1   1   THE006P
2011-07-20  7   7   WIL005P

Проблема

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

В идеале конечный набор результатов должен быть довольно стандартным со столбцами:

summary_day, customer_code, num_deliveries, num_collections

Числовые поля будут столбцом num_spaces из каждого набора результатов. Если у клиента есть записи о сборе и доставке, покажите оба числа. Если у них есть один, а не другой, я использовал COALESCE, чтобы ожидать, что один столбец будет НЕДЕЙСТВИТЕЛЕН, и соответственно присвоить ему значение 0.

Я пытался использовать ПРАВИЛЬНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ В поле customer_code в надежде, что это даст ожидаемые результаты, но единственные результаты, которые я получаю:

2011-07-20, ARR001P, 0, 15
2011-07-20, BAC002P, 0, 1
2011-07-20, BLA001P, 0, 1
2011-07-20, CAR003P, 0, 6
2011-07-20, DIS001P, 0, 2
2011-07-20, DOV001P, 0, 2
2011-07-20, DRY001P, 0, 1
2011-07-20, FAI001P, 3, 5
2011-07-20, INV001P, 0, 2
2011-07-20, MIN001P, 2, 2
2011-07-20, PAL001P, 79, 3
2011-07-20, QUA002P, 0, 1
2011-07-20, TEC002P, 0, 1
2011-07-20, THE006P, 0, 1
2011-07-20, WIL005P, 0, 7

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

Например, примером может служить клиент NOR001P, который находится в наборе результатов поставок, но не в наборе результатов коллекций ...

Требуется ли ПОЛНОЕ НАРУЖНОЕ СОЕДИНЕНИЕ в этом сценарии? Если так, как я мог бы обойти это, учитывая, что MySQL не поддерживает FULL OUTER JOINs?

Спасибо, что нашли время, чтобы прочитать.

ПОЛНОЕ РЕШЕНИЕ

Благодаря ответу CResults, полное решение было следующим: как вы можете видеть, наборы результатов доставки и сбора были фактически составлены из подзапросов, так что это было немного головной болью!

set @summary_day = '2011-07-20';
select summary_day, customer_code, sum(num_deliveries) as pallet_deliveries, sum(num_collections) as pallet_collections
from
(
        select d.summary_day, d.customer_code, d.num_spaces as num_deliveries, 0 as num_collections from
            (select 
                        @summary_day as summary_day, /* change variable */
                        count(*) as num_cons,
                        sum( coalesce(micro_qty,0) + coalesce(quarter_qty,0) + coalesce(half_qty,0) + coalesce(full_qty,0) + coalesce(ceil(vlu_qty),0) ) as num_spaces,
                        pc.customer_code 
                    from pallet_routes pr
                    inner join pallet_consignments pc on pc.route_id = pr.route_id
                    where pr.date = @summary_day /* today */
                    and pc.type = 'D'
                    group by customer_code
            ) as d
        union all
        select c.summary_day, c.customer_code, 0 as num_deliveries, num_spaces as num_collections from
            (select 
                    @summary_day as summary_day, /* change variable */
                    count(*) as num_cons,
                    sum(coalesce(micro_qty,0) + coalesce(quarter_qty,0) + coalesce(half_qty,0) + coalesce(full_qty,0) + coalesce(ceil(vlu_qty),0)) as num_spaces,
                    pc.customer_code 
                from pallet_routes pr
                inner join pallet_consignments pc on pc.route_id = pr.route_id
                where pr.date = DATE_SUB(@summary_day, INTERVAL 1 DAY) /* Yesterday */
                and pc.type = 'C'
                group by customer_code
            ) as c
) as pallet_summaries
group by summary_day, customer_code

Ответы [ 2 ]

3 голосов
/ 25 июля 2011
SELECT D.summary_day
     , D.customer_code
     , D.num_deliveries
     , COALESCE(C.num_collections, 0) AS num_collections
FROM Deliveries AS D
  LEFT JOIN Collections AS C
    ON D.customer_code = C.customer_code
    AND D.summary_day = C.summary_day

UNION ALL

SELECT C.summary_day
     , C.customer_code
     , 0
     , C.num_collections
FROM Deliveries AS D
  RIGHT JOIN Collections AS C
    ON D.customer_code = C.customer_code
    AND D.summary_day = C.summary_day
WHERE D.summary_day IS NULL

ORDER BY summary_day
       , customer_code
3 голосов
/ 25 июля 2011

Абсолютно не проверено, но попробуйте

Select 
    Date, CustCode, Sum(Num_Cons) as Num_Cons, Sum(Num_Cols) as Num_Cols
from 
(    Select Date, CustCode, Num_Cons, 0 as Num_Cols From Consignments
    UNION ALL
    Select Date, CustCode, 0 as Num_Cons, Num_Cols From Collections
) parcels
group by Date, CustCode
...