【问题标题】:MySQL Order By in Right Join ClauseMySQL Order By in Right Join 子句
【发布时间】:2016-04-03 18:55:37
【问题描述】:

我正在尝试像这样在 MySQL 中进行正确的连接:

SELECT customers.id,customers.firstname,customers.lastname,customers.email,orders.time,orders.notes,pendings.date_updated,pendings.issue,appointments.closed,appointments.job_description,backup_plans.expiration FROM customers
RIGHT JOIN orders
ON customers.id = orders.customer_id
ORDER BY orders.time DESC LIMIT 1
RIGHT JOIN pendings
ON customers.id = pendings.customer_id
ORDER BY pendings.date_updated DESC LIMIT 1
RIGHT JOIN appointments
ON customers.id = appointments.customer_id
ORDER BY appointments.closed DESC LIMIT 1
RIGHT JOIN backup_plans
ON customers.id = backup_plans.customer_id
ORDER BY backup_plans.expiration DESC LIMIT 1

我的意图是:选择客户的姓名和电子邮件,以及最近的订单、待处理、预约和备用计划探索。当我执行这个时,我得到一个语法错误:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RIGHT JOIN pendings
ON customers.id = pendings.customer_id
ORDER BY pendings.d' at line 5

我不熟悉联接,希望能提供任何帮助。


编辑 1:

似乎我需要按照 DanK 的建议进行子查询,如下所示:

SELECT customers.id,customers.firstname,customers.lastname,customers.email,orderstmp.time,orderstmp.notes FROM customers
RIGHT JOIN (
    SELECT orders.time,orders.notes,orders.customer_id FROM orders ORDER BY orders.time DESC LIMIT 1
) as orderstmp ON orderstmp.customer_id = customers.id

但是当我这样做时,我只得到一行结果,而我想要所有客户信息。


编辑 2:

根据 Tom H 的建议,我构建了这个查询:

SELECT
    customers.id,
    SQ_O.time,
    SQ_O.notes
FROM customers
LEFT JOIN (
    SELECT
        customers.id,
        orders.time,
        orders.notes
    FROM customers
    LEFT JOIN orders ON orders.customer_id = customers.id
    ORDER BY orders.time DESC LIMIT 1
) AS SQ_O ON SQ_O.id = customers.id

其中包含所有空白时间和备注字段

SELECT
    customers.id,
    O1.time,
    O1.notes
FROM customers
LEFT JOIN orders AS O1 ON O1.customer_id = O1.id
LEFT JOIN orders AS O2 ON O2.customer_id = customers.id AND O2.time > O1.time WHERE O2.customer_id IS NULL

达到最大执行时间。我猜这是因为与其他方言相比,我不熟悉 MySQL 中的可能性。

我也尝试过这样的相关子查询

SELECT
    customers.firstname,
    customers.lastname,
    customers.email,
    (
        SELECT CONCAT(orders.time,': ',orders.notes)
        FROM orders
        WHERE orders.customer_id = customers.id
        ORDER BY orders.time DESC LIMIT 1
    ) as last_order
FROM customers

但“last_order”列出现空白。


最后,令人失望的编辑

在尝试了一些非常出色的建议后,这些建议帮助我显着地学习了 SQL,我决定编写一个 PHP 脚本来获得我想要的东西。该项目的最后期限有点过了,所以无论什么工作,工作。谢谢大家!

【问题讨论】:

  • 每个查询只能有一个 ORDER BY 语句。
  • #1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 5 行的“RIGHT JOIN pendings ON customers.id = pendings.customer_id ORDER BY pendings.d”附近使用正确的语法
  • 其他人几乎都涵盖了核心问题;但我想知道。为什么要加入RIGHT?您是否期望有 orderspendingsappointmentsbackup_plans 记录而没有关联客户记录?
  • @Uueerdo 因为我是 n00b。感谢您的提示!
  • 对于您的最新编辑,您需要在email 之后和(SELECT 之前使用逗号;并且子查询不应该加入客户,它应该有一个WHERE orders.customer_id = customers.id(引用外部查询是使它“相关”的原因。

标签: mysql sql join sql-order-by


【解决方案1】:

只要您可以相信没有客户拥有他们最近的两个orders 具有相同的time,这应该可以工作:

SELECT c.firstname, c.lastname, c.email, o.*
FROM customers AS c
LEFT JOIN (
   SELECT customer_id, MAX(`time`) AS maxTime
   FROM orders
   GROUP BY customer_id 
) AS lastO ON c.id = lastO.customer_id
LEFT JOIN orders AS o 
   ON lastO.customer_id = o.customer_id
   AND lastO.maxTime = o.`time`
;

只要其他表也可以依赖每个客户只有一个MAX 值,您应该能够为它们附加类似的JOINs。对于客户来说,多个相同的“最后一个”time\date_updated\closed\etc.. 的问题是它们会成倍增加结果。例如,同一客户的orders 中的相同time 对和pending 中的date_updated 对将导致4 行而不是2 行,因为orders 中该客户的每个“最后”行是与pending 中的每个“最后”行配对。

【讨论】:

    【解决方案2】:

    您可以通过子查询或额外的JOINs 来完成此操作。这是每个示例。 (注意:我使用 SQL Server,因此我习惯的某些语法可能在 MySQL 中不受支持)。我只是用 Orders 做这些示例,但希望您可以将这些想法扩展到其他表。

    使用子查询:

    SELECT
        C.id,
        SQ_O.time,
        SQ_O.notes
    FROM
        Customers C
    LEFT OUTER JOIN
    (
        SELECT
            C2.Customer_ID,
            O.time,
            O.notes
        FROM
            Customers C2
        LEFT OUTER JOIN Orders O ON O.customer_id = C2.id
        ORDER BY
            O.time DESC LIMIT 1
    ) SQ_O ON SQ_O.customer_id = C.id
    

    使用多个JOINs:

    SELECT
        C.id,
        O1.time,
        O1.notes
    FROM
        Customers C
    LEFT OUTER JOIN Orders O1 ON O1.customer_id = C.id
    LEFT OUTER JOIN Orders O2 ON O2.customer_id = C.id AND O2.time > O1.time
    WHERE
        O2.customer_id IS NULL -- Basically we're excluding any rows where another order was found with a later time than O1
    

    如果在 Orders.time 中完全匹配是可能的,那么您将需要额外的标准来选择一个。

    【讨论】:

    • 谢谢!这看起来非常接近我想做的事情,但我在方言方面遇到了一些麻烦。我更新了原来的问题。
    • 看起来在您的子查询中您有“customers.id”,但是您在子查询之外将其称为“customer_id”。
    • 我改了,但现在时间和备注字段是空的。
    【解决方案3】:

    每个查询只能有一个ORDER BY 语句。您当然可以使用子查询并将结果集引用为虚拟表,但最终在单个 SELECT 中您只能有一个 ORDER BY

    例如:

    SELECT something
    FROM table
    ORDER BY something -- One order By
    

    将子查询作为虚拟表:

    SELECT something
    FROM (SELECT anotherthing, something
          FROM table
          ORDER BY anotherthing) -- this is an order by in a separate select statement..
    ORDER BY something -- still only one Order by
    

    --------编辑--------

    要获得连接语法方面的帮助,请尝试以下操作:

    SELECT --fields,    
    FROM customers
    RIGHT JOIN orders ON customers.id = orders.customer_id
    RIGHT JOIN pendings ON customers.id = pendings.customer_id
    RIGHT JOIN appointments ON customers.id = appointments.customer_id
    RIGHT JOIN backup_plans ON customers.id = backup_plans.customer_id
    ORDER BY orders.time DESC, pendings.date_updated DESC, appointments.closed DESC, backup_plans.expiration DESC
    LIMIT 1
    

    【讨论】:

    • 关闭,但我需要它做的是选择 每个 客户,以及 LIMIT 订单、待处理等
    • 实际上听起来你想做一个相关的子查询..这有点复杂..在这里阅读语法:en.wikipedia.org/wiki/Correlated_subquery
    • 比我的回答 +1 好
    【解决方案4】:

    试试这个:

    SELECT customers.id,customers.firstname,customers.lastname,customers.email,orders.time,orders.notes,pendings.date_updated,pendings.issue,appointments.closed,appointments.job_description,backup_plans.expiration FROM customers
    RIGHT JOIN orders
    ON customers.id = orders.customer_id
    RIGHT JOIN pendings
    ON customers.id = pendings.customer_id
    RIGHT JOIN appointments
    ON customers.id = appointments.customer_id
    RIGHT JOIN backup_plans
    ON customers.id = backup_plans.customer_id
    ORDER BY orders.time DESC, pendings.date_updated DESC,  appointments.closed DESC,  backup_plans.expiration DESC LIMIT 1
    

    【讨论】:

    • 关闭,但我需要它做的是选择 每个 客户,以及 LIMIT 订单、待处理等
    • 如果一个用户有多个订单比? @tyler-shuster
    • @tyler-shuster 我不认为 mysql 支持这个.. 但我发现 UNION 有一些东西
    猜你喜欢
    • 1970-01-01
    • 2010-11-22
    • 2019-11-29
    • 1970-01-01
    • 2011-10-12
    • 2017-12-07
    • 1970-01-01
    相关资源
    最近更新 更多