【问题标题】:Caching inner query in SQL在 SQL 中缓存内部查询
【发布时间】:2012-06-26 00:22:56
【问题描述】:

如何在 SQL 下进行优化(我的复杂查询的简化视图)。理想情况下,我应该能够缓存第一个 SQL 结果(订单 ID)并在第二个查询中对 OrderLine 表进行某种投影。

任何指针都会有所帮助。

限制 - 我无法创建临时表、游标或过程/函数。我正在连接到 Oracle 10g。

SELECT 'Object_id', id, mod_id FROM
(
    (Select 'Order_id', order_id, mod_id FROM Orders)
    UNION
    (select 'Order_line_id', order_line_id, mod_id FROM OrderLine 
        WHERE order_id IN (Select order_id FROM Orders)
    )
) 

【问题讨论】:

    标签: sql optimization query-optimization


    【解决方案1】:

    优化器负责优化您的查询;放松,让它做自己的事情。

    您尝试的任何显式缓存都将涉及临时表(您已排除)之类的内容,因此您只能通过使用 CTE(公用表表达式,又名 WITH 子句)来使公用查询更加明确命名公共子查询。但是优化器可能会以同样的方式处理事情。

    您可以将 IN 子句替换为 JOIN;那可能会更快。同样,优化器可能会这样做。但是,这不是缓存操作;这是一个标准的查询重写。

    【讨论】:

      【解决方案2】:

      您可以根据以下示例设计查询:

      WITH CTE AS
      (
          Select 'Order_id' Descr, order_id, mod_id FROM Orders
      )
      , CTE2 AS
      (
          SELECT * FROM CTE
          UNION
          SELECT 'Order_line_id' Descr, order_line_id, mod_id FROM OrderLine ol
          WHERE EXISTS (Select order_id FROM CTE WHERE order_id = ol.order_id)
      )
      SELECT * FROM CTE2;
      

      【讨论】:

        【解决方案3】:

        选择 order_id、mod_id 从订单o 内连接订单线 ol on o.order_id = ol.order_line_id

        【讨论】:

          【解决方案4】:

          您也许可以删除此行:

           WHERE order_id IN (Select order_id FROM Orders)
          

          如果您的数据库具有完整性,则不允许出现孤儿,并且此行不会过滤任何内容。

          【讨论】:

            【解决方案5】:
            with myOrders as (
              select order_id,
                     mod_id
              from   Orders
            )
            select 'order_id' obj_type,
                   order_id,
                   mod_id
            from   myOrders
            
            union all
            
            select 'order_line_id' obj_type,
                   order_line_id,
                   mod_id
            from   OrderLine
            join   myOrders
            on     OrderLine.order_id = myOrders.order_id;
            

            【讨论】:

              【解决方案6】:

              您可以尝试以下类似的方法...

              SELECT DISTINCT 'Object_id', id, mod_id
              FROM
              (
                  SELECT
                      CASE
                          WHEN CROSSNUM = 1 THEN 'Order_ID'
                          ELSE 'Order_Line_ID'
                      END AS Object_ID,
                      CASE
                          WHEN CROSSNUM = 1 THEN order_id
                          ELSE order_line_id
                      END AS id,
                      CASE
                          WHEN CROSSNUM = 1 THEN Orders.mod_id
                          ELSE OrderLine.mod_id
                      END AS mod_id
                  FROM
                      (Select 'Order_id', order_id, mod_id FROM Orders) Orders
                  LEFT JOIN (select 'Order_line_id', order_line_id, mod_id FROM OrderLine) OrderLine
                      ON Orders.Order_id = OrderLine.Order_Id
                  CROSS JOIN
                  (
                      SELECT 1 AS CROSSNUM FROM DUAL
                      UNION ALL
                      SELECT 2 AS CROSSNUM FROM DUAL
                  ) X
              WHERE
                  NOT (CROSSNUM = 2 AND order_line_id IS NULL)
              )
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-03-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-05-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多