2016-04-29 42 views
0

我目前正在为一个需要显示订单延迟多久的电子商务系统进行报告。我有订单的预计交货日期的日志,并能够获得最初和最后日期,但做比较预计日期等更复杂的事情证明是有问题的。MySQL:引用子查询列

A(简体版)我的查询如下:

SELECT orders.order_id, 
     orders.date_dispatched AS actual_dispatch_date, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id ASC 
      LIMIT 1 
     ) AS initial_delivery_projection, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id DESC 
      LIMIT 1 
     ) AS final_delivery_projection 
FROM orders 
-- and some other joins here for additional report data 

(仅供参考,我在整理上的ID,而不是日期这里,因为调度预测可以向前和向后,例如如果库存货物提前发货)。

这样可以提取一些有关订单预计交货历史的原始数据,但我想对数据进行一些额外的分析,例如初始预计出货日期,最终预计出货日期预计出货日期和实际发货日期。这是我遇到麻烦的地方。

我试着在我的SELECT子句中添加一个DATEDIFF(final_delivery_projection, initial_delivery_projection)列,以便查看给定的传递预测已经下滑了多少天,但是MySQL不会拥有它。在字段列表

SELECT orders.order_id, 
     orders.date_dispatched AS actual_dispatch_date, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id ASC 
      LIMIT 1 
     ) AS initial_delivery_projection, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id DESC 
      LIMIT 1 
     ) AS final_delivery_projection, 
     DATEDIFF(final_delivery_projection - initial_delivery_projection) AS projection_days_revised 
FROM orders 
-- and some other joins here for additional report data 

未知列final_delivery_projection想必你不能在select语句如果别名指的是子选择在同一语句中使用别名。

我也希望能够根据预测的结果排除WHERE子句中的顺序。例如,我想排除最终预计出货日期在最初预计日期之前下落的所有订单,理由是我只对正在进行的订单感兴趣,而不是提前发货的订单。

正在提取和处理我试图在同一个语句中获得的数据,或者我将不得不在客户端做一些后处理来处理类似这样的事情?如果在SQL中是可行的,那么它是如何完成的?

+0

DATEDIFF的语法是否正确? 'DATEDIFF(datepart,startdate,enddate)'是我使用的。 – Matt

+0

我在DATEDIFF上没有收到任何语法错误,文档说它只有两个参数 – GordonM

回答

0

我花了很多时间研究这个问题,这个问题是与MySQL的一个基本问题,这意味着你不能引用外部查询在内部查询中,如果内部查询位于查询的FROM部分中,即使您可以在内部查询位于SELECT部分​​时引用外部查询。

至于从交货日期历史记录中获取第一个和最后一个记录,我发现了这个查询可以产生可接受的性能的正确结果。

SELECT odr.order_id, 
    first_change.projected_date AS initial_projected_dispatch_date, 
    last_change.projected_date AS final_projected_dispatch_date 
FROM order AS odr 
LEFT JOIN (
    SELECT 
     order_id, 
     MIN(order_delivery_projection_id) AS first_id, 
     MAX(order_delivery_projection_id) AS last_id 
    FROM order_delivery_projections 
    GROUP BY order_id 
) AS change_record_finder ON change_record_finder.order_id = odr.order_id 
LEFT JOIN order_delivery_projections AS first_change ON first_change.order_delivery_projection_id = change_record_finder.first_id 
LEFT JOIN order_delivery_projections AS last_change ON last_change.order_delivery_projection_id = change_record_finder.last_id 
WHERE -- where clauses go here 

马特的解决方案将在其他SQL口味很成功,但MySQL的缺乏所需要的功能,让他以其他方式正确答案的工作。

1

我相信select的值是同时生成的。所以日期差异可能无法计算,因为当时可能不知道别名值。如果你重构Select,你可能会得到你正在寻找的结果。此外,这可以让您访问额外的表值,您可能需要额外的表值来进一步分析子查询/数据集。

SELECT orders.order_id, 
     orders.date_dispatched AS actual_dispatch_date, 
     First.Projected_Date AS initial_delivery_projection, 
     Current.Projected_Data AS final_delivery_projection, 
     dateDiff(Current.Projected_date,First.Projected_date) 
FROM orders O 
LEFT JOIN (SELECT projected_date, Order_ID 
      FROM order_delivery_projections 
      ORDER BY order_delivery_projection_id ASC 
      LIMIT 1) First 
    ON First.order_id = O.order_id 
LEFT JOIN (SELECT projected_date, Order_ID 
      FROM order_delivery_projections 
      ORDER BY order_delivery_projection_id DESC 
      LIMIT 1) 
    ON Current.Order_ID = O.Order_ID 

order_Delivery_projections中可能不存在Orders中的Order_ID吗?如果是这样,日期差异空值也可能导致错误...

+0

这是行得通的,但它也很慢。我会接受,如果没有更好的解决方案 – GordonM

+0

它真的不应该慢... Orders.OrderID和order_Delivery_projections.orderID和order_Delivery_Projection_ID上的索引? – xQbert

+0

我认为问题是ORDER BY ASC获得第一个记录和ORDER BY DESC在同一张桌子上得到最后一个。我的怀疑是它导致MySQL做了一些脑死亡的事情。没有性能问题,如果我做一个或另一个,但两个似乎杀死它。 – GordonM

0

环顾四周你需要使用派生表,以便访问选择查询中的别名。看到here从更多信息

尝试此查询:

SELECT orders.order_id, 
     orders.date_dispatched AS actual_dispatch_date, 
     initial_delivery_projection, 
     final_delivery_projection, 
     DATEDIFF(final_delivery_projection - initial_delivery_projection) AS projection_days_revised 
FROM (
    SELECT orders.order_id, 
     orders.date_dispatched AS actual_dispatch_date, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id ASC 
      LIMIT 1 
     ) AS initial_delivery_projection, 
     (
      SELECT projected_date 
      FROM order_delivery_projections 
      WHERE order_id = orders.order_id 
      ORDER BY order_delivery_projection_id DESC 
      LIMIT 1 
     ) AS final_delivery_projection 
    FROM orders) z 
+0

这不起作用,因为MySQL说orders.order_id是一个未知列。我不认为你可以在内部查询中使用外部查询引用 – GordonM

+0

您是否尝试删除订单。部分选择/两个选择?只是一个猜测。如果不是好运,因为我不确定没有在示例表上搞乱:) – Matt