2013-03-26 46 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

相关问题