左连接后的内连接
Posted
技术标签:
【中文标题】左连接后的内连接【英文标题】:INNER JOIN after LEFT JOIN 【发布时间】:2016-01-12 15:30:17 【问题描述】:我有两个很好用的查询。后者对前者的每一行运行一次。如果可能的话,我想将它们结合起来以提高性能。后者返回 0 行或 1 行。
问题是这两个查询都使用了 INNER JOIN,我需要用 LEFT JOIN 将它们粘合起来。这是否合法,并且是否明确定义了如果在左连接“之后”使用 INNER 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
;
此查询的目的是为每个订单查找客户是否“续订”并在以后购买了另一个相同或类似的产品。
【问题讨论】:
“组合”它们是什么意思。有很多方法可以组合两个查询(UNION、JOINing 结果集、将一个的逻辑合并到另一个)?两者之间有什么关系?在这两个中,您在一堆 INNER 之后都有一个 LEFT JOIN,那么为什么要担心呢? 后者对前者的每一行运行一次。我想在一个shebang中完成整个事情。关系在后者的代码中内联注释。 要清楚,您是否尝试从查询中返回结果集以及额外的零或一行,或者您是否尝试仅从第二个查询中返回零或一行?至于内部加入后的左加入,是的,这绝对是合法的,但我认为我们仍然不完全清楚您的意图。 【参考方案1】:在这里使用 with wloud 很棒,但如果你在 mysql 中 FROM subquery 是你所需要的。
鉴于这个最长的查询 if 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
;
【讨论】:
以上是关于左连接后的内连接的主要内容,如果未能解决你的问题,请参考以下文章