2013-03-26 36 views
3

我有這樣的數據表中的查找開始和結束日期,當一個領域發生變化

FIELD_A FIELD_B  FIELD_D 
249052903 10/15/2011 N 
249052903 11/15/2011 P ------------- VALUE CHANGED 
249052903 12/15/2011 P 
249052903 1/15/2012 N ------------- VALUE CHANGED 
249052903 2/15/2012 N 
249052903 3/15/2012 N 
249052903 4/15/2012 N 
249052903 5/15/2012 N 
249052903 6/15/2012 N 
249052903 7/15/2012 N 
249052903 8/15/2012 N 
249052903 9/15/2012 N 

當曾經在FIELD_D值更改它形成一個組,我需要的最小值和最大值該組中的日期。查詢返回

FIELD_A GROUP_START GROUP_END 
249052903 10/15/2011 10/15/2011 
249052903 11/15/2011 12/15/2011 
249052903 1/15/2012    9/15/2012 

到目前爲止我所見過的例子都使Field_D中的數據是唯一的。這裏的數據可以重複顯示,首先是「N」,然後變成「P」,然後回到「N」。

任何幫助將不勝感激

感謝

回答

1

如果您的SQL實施支持它們,您可以使用分析函數-LAG,LEAD和COUNT()OVER來獲得您的優勢。 SQL小提琴here

WITH EndsMarked AS (
    SELECT 
    FIELD_A, 
    FIELD_B, 
    CASE WHEN FIELD_D = LAG(FIELD_D,1) OVER (ORDER BY FIELD_B) 
     THEN 0 ELSE 1 END AS IS_START, 
    CASE WHEN FIELD_D = LEAD(FIELD_D,1) OVER (ORDER BY FIELD_B) 
     THEN 0 ELSE 1 END AS IS_END 
    FROM T 
), GroupsNumbered AS (
    SELECT 
    FIELD_A, 
    FIELD_B, 
    IS_START, 
    IS_END, 
    COUNT(CASE WHEN IS_START = 1 THEN 1 END) 
     OVER (ORDER BY FIELD_B) AS GroupNum 
    FROM EndsMarked 
    WHERE IS_START=1 OR IS_END=1 
) 
    SELECT 
    FIELD_A, 
    MIN(FIELD_B) AS GROUP_START, 
    MAX(FIELD_B) AS GROUP_END 
    FROM GroupsNumbered 
    GROUP BY FIELD_A, GroupNum; 
+0

感謝您的答案,但是這不會產生正確答案,因爲只返回一行。 EndsMarked只創建一個組 – cooperjv 2013-03-27 20:24:57

+0

您是否運行SQL小提琴?該查詢返回三行 - 完全是您所說的「該查詢應返回的三行」。 – 2013-03-27 21:44:37

+0

感謝您的跟進。這是我的錯誤。查詢返回了正確的數據。感謝所有的幫助。 – cooperjv 2013-03-27 22:35:43

0

不要使用SQL對於這個問題,因爲這是不可能的,因爲它需要記錄之間比較單一表掃描做的SQL。它需要一個完整的表掃描,並且至少需要一個與自身的連接。以命令式語言實施解決方案並不重要,它只需要一次表掃描。 編輯:存儲過程將是最好的。

+1

這種說法完全錯誤。 SQL中的表本質上是無序的。爲了以正確的順序檢索adta,您需要使用'order by'子句,該子句需要多次讀取/寫入數據。 – 2013-03-27 13:04:42

+0

根據理論關係模型,關係是無序的。但是,實際上,可以使用聚集索引按順序存儲表,請參閱http://stackoverflow.com/questions/1251636/what-do-clustered-and-non-clustered-index-actually-mean。此外,解決此問題的SQL將使用多個索引,order_by需要一個索引。而且表格本身只需要按索引讀取一次,而不是像您聲稱的那樣多次讀取。事實上,將此表存儲爲單個順序文件,而不是DBMS中,僅針對此問題,看起來對我來說是最好的解決方案。 – koriander 2013-03-27 13:24:51

1

這是相當容易的使用子查詢在SQL表達:

select Field_A, Field_D, min(Field_B) as Group_Start, max(Field_B) as Group_End 
from (select t.*, 
      (select min(field_B) 
       from t t2 
       where t2.field_A = t.field_A and 
        t2.field_B > t.field_B and 
        t2.Field_D <> t.field_D 
      ) as TheGroup 
     from t 
    ) t 
group by Field_A, Field_D, TheGroup 

這是指派使用相關子組標識符。標識符是Field_B的第一個值,其中Field_D發生更改。

你沒有提到你正在使用的數據庫,所以這使用標準的SQL。

+0

此查詢僅創建兩個組。 TheGroup需要附加條件t2.Field_B> t.Field_B。我仍然認爲存儲過程是一個更快,更容易維護的解決方案。 – koriander 2013-03-27 11:34:37

+0

@koriander。 。 。我向你指出我忘記了'Field_B'上的條件。不過,我不同意你的評論的其餘部分。 – 2013-03-27 13:05:48

+0

我其實很喜歡你的SQL查詢的優雅。但如果性能是一個問題,我肯定會考慮基本的順序文件處理。原始數據看起來像來自日誌,自然排序,不需要索引。 – koriander 2013-03-27 13:28:56

相關問題