【问题标题】:MySQL: Select orders that have completed linesMySQL:选择已完成行的订单
【发布时间】:2013-05-21 04:01:31
【问题描述】:

这一定很简单。

我有两个表:ORDERS 和 ORDER_LINES。非常简单且不言自明;这是一对多的关系。 ORDER_LINES 有一个 FULFILLED 列,其中包含该特定行的完成日期。

这是我需要做的:选择已完成订单的所有 ORDERS.ID;即,对于该特定订单,ORDER_LINES 表中的 FULFILLED 列都不是 NULL。

例子:

订单#1有两行,两行都不为空

订单 #2 有一行为空

查询应该只返回#1,因为它是完整的。

【问题讨论】:

    标签: mysql


    【解决方案1】:
    Select *
    From orders As O
    Where Not Exists    (
                        Select 1
                        From order_lines As OL1
                        Where OL1.Fullfilled Is Null
                             And OL1.OrderId = O.OrderId
                        )
    

    SQL Fiddle version

    使用 In 函数的替代版本:

    Select *
    From orders As O
    Where O.OrderId Not In    (
                              Select OL1.OrderId
                              From order_lines As OL1
                              Where OL1.Fullfilled Is Null
                              )
    

    SQL Fiddle version

    加法

    希望使用聚合函数来实现这一点。虽然下面是一个解决方案,但使用 Exists 和 In 函数的表单比以下查询更好地表达了意图,因此我建议使用这两种形式中的一种:

    Select O.OrderId
    From Orders As O
        Left Join Order_Lines As OL
            On OL.OrderId = O.OrderId
                And OL.Fullfilled Is Null
    Group By O.OrderId
    Having Count(OL.Id) = 0
    

    SQL Fiddle version

    另一种可能表现最好的形式:

    Select O.OrderId
    From Orders As O
        Left Join Order_Lines As OL
            On OL.OrderId = O.OrderId
                And OL.Fullfilled Is Null
    Where OL.Id Is Null
    

    SQL Fiddle version

    【讨论】:

    • 是否有一个“更清洁”的聚合函数来代替嵌套的 SELECT?
    • @JFriend - 从技术上讲,是的,有一种方法可以使用聚合函数来做到这一点,但你为什么要这样做呢?它不会像 Exists 或 In 函数那样表达您的意图。
    • 我只是在考虑一个非常大的数据库(16M 订单行,30 个并发用户)的开销和资源。
    • @JFriend - 我的猜测是使用 In 函数的表单性能最好,但您必须检查执行计划才能确定。
    • @JFriend - 我收回了。实际上,我刚刚发布的最后一个表单可能是最快的。
    【解决方案2】:

    使用左连接并添加条件以查询仅在所需列中不为空的行的选择。像这样。

    SELECT ORDERS.ID 
    FROM ORDERS 
    LEFT JOIN ORDER_LINES 
        ON (ORDERS.ID = ORDER_LINES.ORDER_ID) 
    WHERE ORDER_LINES.ORDER_ID is not null
    

    【讨论】:

    • 这不行...您必须检查已完成的列以查看[每个订单]的所有行是否都已完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    相关资源
    最近更新 更多