如何重构查询以连接表而不是虚拟表?

时间:2011-07-30 01:38:01

标签: sql oracle

我有一个连接了两个虚拟表的查询。有没有办法重构这个查询,以便不是将这些表作为虚拟表,我可以将它们作为常规表加入requests?我无法弄清楚如何使用它们中包含的所有聚合函数等来做到这一点。

SELECT
  tr.source_id,
  temp_tri.qty_requested,
  temp_tri.qty_cancelled,
  temp_palletize.qty_palletized_on_time
FROM
  requests r
JOIN
  (
    SELECT
      request_id,
      SUM(quantity_requested) qty_requested,
      SUM(quantity_cancelled) qty_cancelled
    FROM
      request_items
    GROUP BY request_id
  ) temp_tri ON temp_tri.request_id = r.request_id
JOIN
  (
    SELECT
      tmi.request_id,
      SUM(tmi.quantity) qty_palletized_on_time
    FROM
      manifest_items tmi
    JOIN
      requests tr2 ON tr2.request_id = tmi.request_id
    JOIN
      outbd_containers toc ON toc.manifest_id = tmi.manifest_id
    JOIN
      move_segments ms ON ms.move_to_container_id = (SELECT container_id FROM containers WHERE scannable_id = toc.scannable_id)
    WHERE
      ms.action = 'MOVING'
      AND ms.move_date <= tr2.need_to_ship_by_date
    GROUP BY
      tmi.request_id
  ) temp_palletize ON temp_palletize.request_id = r.request_id
WHERE
  (tr.need_to_receive_by_date BETWEEN (TO_DATE('2011-07-01', 'YYYY-MM-DD') AND TO_DATE('2011-07-02', 'YYYY-MM-DD')))

2 个答案:

答案 0 :(得分:1)

如果您使用的是Oracle,那么简单的方法就是在物化视图中转换您使用它的sql。在下面的示例中,您有一个基于第一个sql的物化视图,通过快速刷新创建。

CREATE MATERIALIZED VIEW aggregated_requests
   BUILD IMMEDIATE
   REFRESH FAST ON COMMIT
   AS 
SELECT
      request_id,
      SUM(quantity_requested) qty_requested,
      SUM(quantity_cancelled) qty_cancelled
    FROM
      request_items
    GROUP BY request_id;

然后你有一个物理表而不是查询。

检查一下: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_6002.htm

答案 1 :(得分:1)

Oracle可以根据需要删除内联视图,因此不要费心去整理它们。 某些形式的解释计划和表格描述(大小,索引等)应该提供更多建议(但可能在一个单独的问题中)。

正如Cheran所指出的那样,你没有显示'tr'表/视图进入事物的位置。

我也会关注这个:

SELECT
      tmi.request_id,
      SUM(tmi.quantity) qty_palletized_on_time
    FROM  manifest_items tmi
    JOIN  requests tr2 ON tr2.request_id = tmi.request_id
    JOIN  outbd_containers toc ON toc.manifest_id = tmi.manifest_id
    JOIN  move_segments ms ON ms.move_to_container_id = 
          (SELECT container_id FROM containers 
          WHERE scannable_id = toc.scannable_id)
    WHERE ms.action = 'MOVING'
    AND   ms.move_date <= tr2.need_to_ship_by_date
    GROUP BY tmi.request_id

并期待用EXISTS重写。我有一个通用规则,除非列实际上是SELECT,否则表不应该在FROM列表中。

连接到tr2 - 您是否在manifest_items中有请求而不在请求表中?

SELECT tmi.request_id,
      SUM(tmi.quantity) qty_palletized_on_time
FROM  manifest_items tmi
WHERE exists
  (SELECT 1
    FROM  outbd_containers toc
    JOIN  containers c ON c.scannable_id = toc.scannable_id
    JOIN  move_segments ms ON c.container_id = ms.move_to_container_id
    WHERE toc.manifest_id = tmi.manifest_id
    AND   ms.action = 'MOVING'
    AND   ms.move_date <= tr2.need_to_ship_by_date)
 GROUP BY tmi.request_id