2016-01-12 6 views
2

У меня есть два вопроса, которые отлично работают. И последний запускается один раз для каждой строки первого. Я хотел бы объединить их, если это возможно, для производительности. Последний возвращает ноль или одну строку.INNER JOIN after LEFT JOIN

Проблема в том, что оба запроса используют INNER JOINs. Мне нужно приклеить их с помощью LEFT JOIN. Является ли это законным, и хорошо ли определено, что произойдет, если INNER JOIN будет использоваться после «LEFT JOIN». И, наконец, будет ли такая махинация иметь какие-либо штрафные санкции за существующий подход, который является «быстрым»?

Для справки, и мне очень жаль, если это TMI, вот мой первый запрос:

SELECT 
    pmt_attempts.user_id, 
    CONCAT(DATE_FORMAT(attempt_time_end, '%Y') + 2, DATE_FORMAT(attempt_time_end, '-%m-%d')) as date_expired, 
    course_sku, 
    um_fn.meta_value AS 'shipping_first_name', 
    um_ln.meta_value AS 'shipping_last_name', 
    um_cr.meta_value AS 'credentials', 
    pmt_orders.promocode_used, 
    pmt_promocodes.sales_channel 
FROM 
    pmt_attempts 
INNER JOIN 
    pmt_courses 
    ON pmt_attempts.course_id = pmt_courses.course_id 
INNER JOIN 
    pmt_orders 
    ON pmt_orders.order_id = pmt_attempts.order_id 
INNER JOIN 
    wp_usermeta um_fn 
    ON pmt_orders.user_id = um_fn.user_id 
    AND um_fn.meta_key = 'shipping_first_name' 
INNER JOIN 
    wp_usermeta um_ln 
    ON pmt_orders.user_id = um_ln.user_id 
    AND um_ln.meta_key = 'shipping_last_name' 
LEFT JOIN 
    wp_usermeta um_cr 
    ON pmt_orders.user_id = um_cr.user_id 
    AND um_cr.meta_key = 'credentials' 
INNER JOIN 
    pmt_order_course 
    ON fk_order_id = pmt_attempts.order_id 
    AND fk_course_id = pmt_attempts.course_id 
LEFT JOIN 
    pmt_promocodes 
    ON pmt_orders.promocode_used = pmt_promocodes.promocode_text 
WHERE 
    attempt_time_end >= '2014-01-01' AND <--- CONFIGURABLE REPORT PARAM 
    attempt_time_end < '2014-02-01' AND <--- CONFIGURABLE REPORT PARAM 
    attempt_complete = 'Y' AND 
    (unenroll_date IS NULL OR unenroll_date = '0000-00-00') AND 
    1 
ORDER BY 
    attempt_time_end 
; 

и вот второй запрос:

SELECT 
    course_sku, 
    pmt_orders.order_date, 
    attempt_time_end, 
    pmt_order_course.unenroll_date 
FROM 
    pmt_order_course 
INNER JOIN 
    pmt_orders ON 
    pmt_orders.order_id = pmt_order_course.fk_order_id 
INNER JOIN 
    pmt_courses ON 
    pmt_courses.course_id = pmt_order_course.fk_course_id 
LEFT JOIN 
    pmt_attempts ON 
    pmt_attempts.course_id = pmt_courses.course_id AND 
    pmt_attempts.order_id = pmt_orders.order_id AND 
    pmt_attempts.attempt_complete = 'Y' 
WHERE 
    pmt_orders.user_id = 928 AND <--- FROM FIRST QUERY ROW 
    course_sku LIKE 'BL%' AND <--- FIRST TWO LETTERS OF FIRST QUERY ROW + % 
    pmt_orders.order_date > '2012-12-14' <--- FROM FIRST QUERY ROW 
ORDER BY 
    pmt_orders.order_date 
LIMIT 
    1 
; 

Цель этого запроса найти для каждого заказа, был ли клиент «обновлен» и приобрел другой продукт того же или аналогичного продукта позднее.

+0

Что вы имеете в виду под «Объединить» их. Существует много способов объединить два запроса (UNION, JOINing на наборах результатов, включая логику одного в другой)? Какова взаимосвязь между ними? В обоих из них у вас есть LEFT JOIN после кучи INNER, так зачем беспокоиться? – JNevill

+0

Последний запускается один раз для каждой строки первого. Я хотел бы сделать все это в одном shebang. Эта связь аннотируется inline в коде последней. –

+0

, чтобы быть понятным, пытаетесь ли вы вернуть как результат, так и дополнительный нуль или одну строку из запроса, или вы пытаетесь вернуть ТОЛЬКО нуль или одну строку из второго запроса? Что касается вступления в должность после внутреннего присоединения, да, это абсолютно легально, но я думаю, что мы все еще не полностью избавлены от ваших намерений. – user2366842

ответ

1

Использование с wloud будет большим здесь, но если вы находитесь в MySQL FROM subquery - это то, что вам нужно.

Учитывая, что этот длинный firest запрос, если Q1, и этот столбец course_sku от таблицы pmt_orders, мы можем написать:

SELECT 
    course_sku, 
    pmt_orders.order_date, 
    attempt_time_end, 
    pmt_order_course.unenroll_date 
FROM 
    (Q1 here) q1 
INNER JOIN pmt_order_course ON (pmt_orders.user_id = q1.user_id AND pmt_orders.course_sku LIKE CONCAT(q1.course_sku,'%') AND pmt_orders.order_date > q1.date_expired) 
INNER JOIN pmt_orders ON (pmt_orders.order_id = pmt_order_course.fk_order_id) 
INNER JOIN pmt_courses ON (pmt_courses.course_id = pmt_order_course.fk_course_id) 
LEFT JOIN pmt_attempts ON (pmt_attempts.course_id = pmt_courses.course_id AND pmt_attempts.order_id = pmt_orders.order_id AND pmt_attempts.attempt_complete = 'Y') 
WHERE 1 = 1  
ORDER BY 
    pmt_orders.order_date 
LIMIT 
    1 
; 
+0

Это отлично работает, спасибо –