2014-04-12 72 views
0

我有一個包含審計表的數據庫。這些審計表包含主表中記錄的副本,從觸發器複製而來,我需要從這些審計記錄中創建一種時間點報告。子查詢中的DB2嵌套關聯表引用

這些表格每個都有一個updated_at列,它是插入記錄的時間戳 - 將它與id列混合使用,我們可以精確定位特定的記錄(我提及這是因爲這些id列在這些列中不能唯一表)。

我需要做的是用某些列過濾器拉記錄,然後只獲得那些記錄的「最近」版本(所以通常是MAX(updated_at)類型返回集)。然後,我需要加入另外3個審計表,並從中獲取相關記錄 - 但是「最近」記錄(最後一個表,audit_products我用於獲取與相關記錄關聯的產品數的COUNT()) ...但只能從查詢的最初部分返回的updated_at - 這是我的問題。

這是查詢(不工作),我想運行...理論:

SELECT gr.id, gr.title_e, gr.title_f, wp.updated_at, wp.to_epmd_orig, wp.to_epmd_revise, wp.to_epmd_actual, lc.code_e, lc.code_f, pr.total 
    FROM (
    SELECT fw.id, fw.group_id, fw.updated_at, fw.to_epmd_orig, fw.to_epmd_revise, fw.to_epmd_actual, fw.to_epmd_late_code 
     FROM audit_pc_pub_workplans AS fw 
     RIGHT JOIN (
     SELECT id, MAX(updated_at) AS updated_at 
      FROM audit_pc_pub_workplans 
      WHERE completed = 1 AND DATE(to_epmd_actual) BETWEEN '2013-04-01' AND '2014-03-31' 
      GROUP BY id 
    ) AS aw ON (aw.id = fw.id AND aw.updated_at = fw.updated_at) 
) as wp 
    LEFT JOIN (
    SELECT fg.id, fg.updated_at, fg.title_e, fg.title_f 
     FROM audit_groups AS fg 
     RIGHT JOIN (
     SELECT id, MAX(updated_at) AS updated_at 
      FROM audit_groups 
      WHERE updated_at <= wp.updated_at AND del_date IS NULL 
      GROUP BY id 
    ) AS ag ON (ag.id = fg.id AND ag.updated_at = fg.updated_at) 
) AS gr ON (gr.id = wp.group_id) 
    LEFT JOIN (
    SELECT fc.id, fc.code_e, fc.code_f 
     FROM audit_wp_late_codes AS fc 
     RIGHT JOIN (
     SELECT id, MAX(updated_at) AS updated_at 
      FROM audit_wp_late_codes 
      WHERE updated_at <= wp.updated_at AND delete_date IS NULL 
      GROUP BY id 
    ) AS ac ON (ac.id = fc.id AND ac.updated_at = fc.updated_at) 
) AS lc ON (lc.id = wp.to_epmd_late_code) 
    LEFT JOIN (
    SELECT fp.prod_group, COUNT(DISTINCT fp.id) AS total 
     FROM audit_products AS fp 
     RIGHT JOIN (
     SELECT id, MAX(updated_at) AS updated_at 
      FROM audit_products 
      WHERE updated_at <= wp.updated_at AND del_date_2 IS NULL 
      GROUP BY id 
    ) AS ap ON (ap.id = fp.id AND ap.updated_at = fp.updated_at) 
     GROUP BY fp.prod_group 
) AS pr ON (pr.prod_group = gr.id) 
ORDER BY gr.title_e ASC 
; 

爲了完整起見,我把所有的列名在那裏原樣是,但作爲外人,你可以明顯地忽略其中的一些。關鍵的是id類型的列,主要用於ON()語句,而所有表格都有updated_at列。

這個問題特指我在LEFT JOIN的所有子子查詢中對wp.updated_at的引用。我讀了一遍,發現我在使用一個關鍵詞LATERAL時應該允許我公開wp表,並且它實際上允許我運行查詢......但是當我運行該查詢時(通過方式,audit_products表有大約8M記錄),我在等待2小時後放棄。

有什麼辦法可以將這個查詢重寫成在合理的時間內工作嗎?我甚至會接受15-30分鐘的時間跑......不是幾個小時。

任何幫助,將不勝感激!

+0

那麼,使用'DATE(to_epmd_actual)'會導致它忽略該列上的索引(的相關部分)。使用'to_epmd_actual> ='2013-04-01'和to_epmd_actual <'2014-04-01''(參見[本博客](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/) what-do-between-and-the-devil-have-in-common.aspx)爲什麼)。能夠得到一些樣本數據/期望的結果會很好,但這應該是可以簡化的,是的 - 這將有助於瞭解需要什麼以及可以刪除什麼(我對使用RIGHT JOIN有點懷疑)在這個情況下)。 –

+0

是的,使用'DATE()'投射字段,以便我可以指定一個沒有時間的日期。這樣做的延遲很小,所以我並不擔心這一點。 「RIGHT JOIN」是故意的,儘管真的應該是一個'INNER JOIN' ......儘管如此,我不認爲它們正在導致真正的減速。 –

回答

1

首先,我不認爲你需要在你的查詢外部連接。其次,考慮使用OLAP函數ROW_NUMBER()來檢索最新記錄 - 它通常比聚合更快。例如:

SELECT gr.id, gr.title_e, ... 
    FROM (
    SELECT fw.id, ... fw.to_epmd_late_code, 
      ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) rn 
     FROM audit_pc_pub_workplans 
     WHERE completed = 1 AND DATE(to_epmd_actual) BETWEEN '2013-04-01' AND '2014-03-31' 
) as wp 
    INNER JOIN LATERAL (
    SELECT fg.id, fg.updated_at, fg.title_e, fg.title_f, 
      ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) 
     FROM audit_groups 
     WHERE updated_at <= wp.updated_at and wp.rn = 1 AND del_date IS NULL 
) AS gr ON (gr.id = wp.group_id) 
    ... 
+0

感謝您使用該語法示例。我有一些除了'audit_products'表之外的所有工作,因爲我需要做一個聚合計數,我不能找出一種方式來做到這一點,而不涉及子子查詢。只要發生這種情況,查詢就會永遠運行。 –