2016-05-29 4 views
0

Вот мой SQL запрос:INNER JOIN на 2 таблицы возвращает неправильные значения

SELECT SUM(amz_event_shipment_items.quantity), 
     amz_event_shipment_items.seller_sku 

FROM amz_event_shipment_items 

INNER JOIN amz_event_fees   ON amz_event_shipment_items.id = amz_event_fees.shipment_item_id 
INNER JOIN amz_shipment_events ON amz_shipment_events.id = amz_event_shipment_items.shipment_event_id 

WHERE amz_event_fees.currency = 'USD' 
     AND amz_shipment_events.event_type <> 'RefundEvent' 
     AND amz_shipment_events.posted_date BETWEEN '2016-5-1 07:00:00' AND '2016-5-7 06:59:59' 

GROUP BY amz_event_shipment_items.seller_sku 


Но возвращаемые значения слишком высоки ... Не может иметь смысл для меня ...

Я что-то пропустил?

Редактировать

Many shipment_events for each date 

Each shipment_event HAS MANY shipment_item/BELONGS TO ONE event 

Each shipment_item HAS MANY shipment_fee/BELONGS TO ONE item 
+0

Кажется правильным. Какой результат вы ожидаете? –

+0

скажите, для одного seller_sku, ожидаемых значений 13, я получаю это 15 .. для других sku, значение ожидается 75, я получаю 83 –

+0

Мне нужно посмотреть некоторые данные примера. Скрипка была бы приятной. Какие результаты вы ожидаете? –

ответ

1

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

Таким образом, задача устранения дубликатов занимает слишком много времени.

Две идеи здесь:

Первая идея: Исключите дублирует сразу

Вместо joning на сборы, мы собираем взносы до вступления:

select 
    sum(i.quantity), 
    i.seller_sku 
from amz_event_shipment_items i 
join -- join with only one record per ID to substitute an EXISTS clause 
(
    select distinct shipment_item_id 
    from amz_event_fees 
    where f.currency = 'USD' 
) f on f.shipment_item_id = i.id 
and exists 
(
    select * 
    from amz_shipment_events e 
    where e.event_type <> 'RefundEvent' 
    and e.posted_date between '2016-05-01 07:00:00' and '2016-05-07 06:59:59' 
    and e.id = i.shipment_event_id 
) 
group by i.seller_sku; 

Вторая идея: Pre-заполнитель значения

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

select 
    sum(i.pre_sum_quantity), 
    i.seller_sku 
from 
(
    select seller_sku, shipment_event_id, sum(quantity) as pre_sum_quantity 
    from amz_event_shipment_items 
    where exists 
    (
    select * 
    from amz_event_fees f 
    where f.currency = 'USD' 
    and f.shipment_item_id = amz_event_shipment_items.id 
) 
    group by seller_sku, shipment_event_id 
) i 
where exists 
(
    select * 
    from amz_shipment_events e 
    where e.event_type <> 'RefundEvent' 
    and e.posted_date between '2016-05-01 07:00:00' and '2016-05-07 06:59:59' 
    and e.id = i.shipment_event_id 
) 
group by i.seller_sku; 

В случае, если есть только несколько типов событий, вы можете также попытаться избавиться от <>, что делает его немного более вероятно, используется индекс:

where e.event_type in ('EarlyPaymentEvent','LatePaymentEvent') 

(В этом случае он может заплатить, чтобы иметь индекс, где event_type приходит до posted_date.)

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

+0

вы, красавец, первый, который вы предложили (с ключевым словом 'DISTINCT' в нем), черт возьми, чем тот, который был принят в ответе ... Профилирование показывает, что принятый запрос ответа занимает от 26 секунд до 39 секунд с моим данным набор тестовых данных ... и этот, первый запрос в этом ответе дает мне время мин 0.70 и макс 0.90 ... Мне это нравится ... и я обязан и благодарен вам ... –

1

Вы перемножения количества по количеству сборов. Используйте предложение IN или EXISTS, когда ищете простое существование.

select 
    sum(i.quantity), 
    i.seller_sku 
from amz_event_shipment_items i 
where exists 
(
    select * 
    from amz_event_fees f 
    where f.currency = 'USD' 
    and f.shipment_item_id = i.id 
) 
and exists 
(
    select * 
    from amz_shipment_events e 
    where e.event_type <> 'RefundEvent' 
    and e.posted_date between '2016-05-01 07:00:00' and '2016-05-07 06:59:59' 
    and e.id = i.shipment_event_id 
) 
group by i.seller_sku; 

(MySQL, как известно, медленно на IN пунктах иногда, поэтому я использую EXISTS здесь, хотя мне нравится IN лучше.)

+0

, кажется, ближе к моему требуемому подходу, но проблема в том, что «выберите e.shipment_event_id от amz_shipment_events e 'не существует –

+0

О, извините. Это показывает, что я был смущен. Для элемента есть только одно событие, поэтому мой ответ прост. Я собираюсь удалить его. –

+0

см. Мой обновленный вопрос –

0

Возможно, что один из ваших объединений возвращается больше записей, чем вы ожидаете , Я бы попробовал просто сделать select * и отсортировать по sku и eyeball результаты.

+0

сделали это, поэтому я и говорю, что получаю больше, чем ожидалось –

+0

Ницца, проголосовав после того, как он редактировал свой вопрос. –

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