如何有效地返回3个表中的结果MySQL

时间:2016-01-09 19:38:17

标签: mysql sql join

Howdie do,

我有以下3个表:order,manifest和tracking_updates。现在,每个订单都有名为manifest_id的外键,它引用清单表。清单中可以有多个订单。 tracking_updates表有一个名为order_id的外键,它引用了订单表。

现在,清单表包含一个名为upload_date的列。该列upload_date是我需要使用的列,以确定订单是否在过去30天内上传。

tracking_update表可以包含每个订单的许多更新,因此,我必须为符合以下条件的每个订单返回最新的跟踪更新状态:

1. orders < 30 days, any delivery status 
2. orders > 30 days, not delivered

请参阅下表

**Order**

ID |  manifest_id

1  |  123

2  |  123

3  |  456

**Manifest**:

ID |  upload_date

123  |  2015-12-15 09:31:12

456  |  2015-10-13 09:31:12

**Tracking Update**:

order_id  | status_type | last_updated

1         |  M          | 2015-12-15 00:00:00

1         |  I          | 2015-12-16 07:20:00

1         |  D          | 2015-12-17 15:20:00

2         |  M          | 2015-12-15 00:00:00

2         |  D          | 2015-12-16 15:20:00

3         |  M          | 2015-10-13 00:00:00

3         |  I          | 2015-10-14 12:00:00

3         |  E          | 2015-10-15 13:50:00

这就是上面的订单

的结果集
**Result Set**

order_id  | manifest_id | latest_tracking_update_status

1         | 123         | D

2         | 123         | D

3         | 456         | E

正如您所看到的,订单1,2被分配给清单123,清单在过去30天内上传,其最新的跟踪更新显示了&#39; D&#39;交付。所以这两个订单应该包含在结果集中。

订单3早于30天,但尚未根据最新的tracking_update status_type发送,因此它应显示在结果集中。

现在,tracking_update表以及所有订单的超过100万次更新。所以我真的想提高效率

目前,我有以下疑问。

查询#1会返回过去30天内上传的订单及其相应的最新跟踪更新

SELECT 
fgw247.order.id as order_id,
    (SELECT 
        status_type
    FROM 
        tracking_update as tu
    WHERE 
        tu.order_id = order_id
    ORDER BY 
        tu.ship_update_date DESC
    LIMIT 
        1
    ) as latestTrackingUpdate
FROM 
    fgw247.order, manifest
WHERE
    fgw247.order.manifest_id = manifest.id 
AND
    upload_date >= '2015-12-12 00:00:00'

查询#2返回tracking_update表中每个订单的order_id和最新跟踪更新:

SELECT tracking_update.order_id,
    substring_index(group_concat(tracking_update.status_type order by tracking_update.last_updated), ',', -1)
FROM 
    tracking_update
WHERE 
    tracking_update.order_id is not NULL
GROUP BY tracking_update.order_id

我只是不确定如何合并这些查询以获得符合条件的订单:

  1. 订单&lt; 30天,任何交付状态
  2. 订单&gt; 30天,未送达
  3. 任何想法都会非常感激。

    *更新*

    这是当前查询,这要归功于所选答案:

    select 
        o.id, t.maxudate, tu.status_type, m.upload_date
    from 
        (select order_id, max(last_updated) as maxudate from tracking_update group by order_id) t
    inner join 
        tracking_update tu on t.order_id=tu.order_id and t.maxudate=tu.last_updated
    right join 
        fgw247.order o on t.order_id=o.id
    left join 
        manifest m on o.manifest_id=m.id
    where 
        (tu.status_type != 'D' and tu.status_type != 'XD' and m.upload_date <='2015-12-12 00:00:00') or m.upload_date >= '2015-12-12 00:00:00'
    LIMIT 10
    

    更新

    这是非常有效地连接三个表的当前查询

    SELECT 
        o.*, tu.*
    FROM
        fgw247.`order` o
    JOIN
        manifest m
    ON
        o.`manifest_id` = m.`id` 
    
    JOIN
        `tracking_update` tu
    ON
        tu.`order_id` = o.`id` and tu.`ship_update_date` = (select max(last_updated) as last_updated from tracking_update where order_id = o.`id` group by order_id)
    WHERE
        m.`upload_date` >= '2015-12-14 11:50:12' 
        OR 
            (o.`delivery_date` IS NULL AND m.`upload_date` < '2015-12-14 11:50:12')
    LIMIT 100
    

2 个答案:

答案 0 :(得分:1)

有一个子查询,可以从跟踪表中为每个订单返回最新的更新日期。在跟踪,订单和清单表上加入此子查询,以获取详细信息并根据where子句中的上传日期进行过滤:

select o.order_id, t.maxudate, tu.status_type, m.upload_date
from (select order_id, max(update_date) as maxudate from tracking_update group by order_id) t
inner join tracking_update tu on t.order_id=tu.order_id and t.maxudate=tu.update_date
right join orders o on t.order_id=o.order_id
left join manifests m on o.manifest_id=m.manifest_id
where (tu.status_type<>'D' and curdate()-m.upload_date>30) or curdate()-m.upload_date<=30

在where子句中使用union查询而不是or条件可能更有效。

答案 1 :(得分:0)

您可以使用第二个查询结果执行JOIN,例如

SELECT 
fgw247.order.id as order_id,
xx.some_column,
    (SELECT 
        status_type
    FROM 
        tracking_update as tu
    WHERE tu.order_id = order_id
    ORDER BY 
        tu.ship_update_date DESC
    LIMIT 
        1
    ) as latestTrackingUpdate
FROM 
    fgw247.order JOIN manifest
ON fgw247.order.manifest_id = manifest.id 
JOIN (
SELECT tracking_update.order_id,
    substring_index(group_concat(tracking_update.status_type order by tracking_update.last_updated), ',', -1) AS some_column
FROM 
    tracking_update
WHERE 
    tracking_update.order_id is not NULL
GROUP BY tracking_update.order_id ) xx ON xx.order_id = fgw247.order.id

WHERE upload_date >= '2015-12-12 00:00:00'