2010-08-27 45 views
0

我期待返回包含了一組表中每個聯繫人的以下信息:返回一審跨多個表的值(並返回相關的列)

Contact_id | first_Event_date | first_Event_id | event_type 
id123456  | 01/12/2007   | eveid123456  | table1 
id456455  | 05/06/1999   | eveid456585  | table4 

當數據反映的第一個事件每個聯繫人都曾參與(可以包含在最多8個表中的任何一箇中),而event_type告訴你來自哪個表的事件。

我有以下查詢腳本作爲起點,它試圖拉只contact_id和event_date時工作正常,但當我嘗試還包括event_id時,它似乎任意從一個不正確的地方拉一個ID :

SELECT 
table1.contact_id    AS contact_id 
MIN(table1.date_received)  AS event_date 
table1.event_id     AS event_id 
FROM table1 
GROUP BY table1.contact_id 
UNION 
SELECT 
table2.contact_id    
MIN(table2.date_received)  
table2.event_id     
FROM table2 
GROUP BY table2.contact_id 

這對錶3-6重複。我知道我還需要在GROUP BY子句中包含table1.event_id等,但是當我這樣做時,它將爲每個聯繫人(對於每個表)返回每個事件的所有提及,因此一個聯繫人有多個行返回給table1子查詢最多應該返回1行。

此外,在情況下幫助並不是所有的聯繫人會出現在所有的表(但會出現在所有的表至少一次),我使用SQL Server提前2005年

感謝: )

回答

0

嘗試使用UNION ALL合併表以返回每個源表的第一個結果,然後運行外部查詢以獲取所有表中最早的結果。

在此示例中,第一步選擇到臨時表中,第二步選擇臨時表。這將有可能進行這個操作作爲一個單一的嵌套查詢,但更多的混亂閱讀:

第1步 - 最早獲得一行從每個表中的每個接觸

SELECT contact_id , 
     event_id , 
     date_received 
INTO #firstEventsAllTables  
FROM ( SELECT contact_id , 
        event_id , 
        date_received, 
        ROW_NUMBER() OVER (PARTITION BY contact_id 
             ORDER BY date_received 
            ) AS rn 
      FROM table1  
     ) AS t1 
WHERE rn = 1 

UNION ALL  


SELECT contact_id , 
     event_id , 
     date_received 
FROM ( SELECT contact_id , 
        event_id , 
        date_received, 
        ROW_NUMBER() OVER (PARTITION BY contact_id 
             ORDER BY date_received 
            ) AS rn 
      FROM table2  
     ) AS t2 
WHERE rn = 1 

UNION ALL 

etc... 

第2步 - 找到在所有表

SELECT contact_id , 
     event_id , 
     date_received 
FROM ( SELECT contact_id , 
        event_id , 
        date_received, 
        ROW_NUMBER() OVER (PARTITION BY contact_id 
             ORDER BY date_received 
            ) AS rn 
      FROM #firstEventsAllTables  
     ) AS f 
WHERE rn = 1 

(未經測試)

0

首先每接觸最早的行,我很驚訝,你的查詢運行。 select子句中的每個字段或者需要存在於Group By子句中,或者包含在某種聚合函數中。你的event_id字段不是,所以你應該得到一個錯誤。

其次,要獲得與包含最小值的記錄相關的「其他字段」,OVER關鍵字(爲SQL2005添加)是要走的路。以下查詢將每個聯繫人的最小事件日期添加到結果集的每一行。

SELECT 
    contact_id AS contact_id 
    date_received AS event_date, 
    MIN(date_received) OVER (PARTITION BY contact_id) AS min_event_date 
    event_id AS event_id 
FROM table1 

您不能將OVER位置於where子句中,因此您必須將其包裝在子查詢中才能找到所需的記錄。

SELECT contact_id, event_date, event_id 
FROM (
    SELECT 
    contact_id AS contact_id 
    date_received AS event_date, 
    MIN(date_received) OVER (PARTITION BY contact_id) AS min_event_date 
    event_id AS event_id 
    FROM table1) 
WHERE event_date = min_event_date 

最終的解決方案涉及的子查詢的雙層,我認爲,與UNION像最深的:

SELECT contact_id, event_date, event_id 
FROM (
    SELECT 
    contact_id 
    event_date, 
    MIN(event_date) OVER (PARTITION BY contact_id) AS min_event_date 
    event_date 
    FROM (
    SELECT 
     table1.contact_id AS contact_id 
     table1.date_received AS event_date 
     table1.event_id AS event_id 
    FROM table1 
    UNION 
    SELECT 
     table2.contact_id AS contact_id 
     table2.date_received AS event_date 
     table2.event_id AS event_id 
    FROM table2) 
WHERE event_date = min_event_date 
0

埃德哈珀的方法可能是最好的一個。

只是走一個在黑暗中刺傷樂趣在一個瘋狂的版本,試試這個:

WITH all AS (
    SELECT tbl = 'table1', contact_id, date_received, event_id FROM table1 
    UNION ALL SELECT 'table2', contact_id, date_received, event_id FROM table2 
    UNION ALL SELECT 'table3', contact_id, date_received, event_id FROM table3 
    UNION ALL SELECT 'table4', contact_id, date_received, event_id FROM table4 
) ranked AS (
    SELECT 
     *, flag = row_number() OVER (PARTITION BY contact_id, ORDER BY date_received), 
    FROM All 
) 
SELECT * 
FROM ranked 
WHERE flag = 1 

它看起來很簡單,但它可能會表現不佳。請嘗試一下,讓我們知道它是如何做到的。 :)