将一系列日志数据排序到用户的适当视图中(FIFO同义词)

时间:2013-08-22 14:43:24

标签: sql-server sql-server-2008 tsql

不知道如何找到这个,这就是为什么我提前向社区道歉。

我在将一系列日志数据排序到用户的相应视图时遇到问题。

默认情况下,所有数据都以两种方式记录:插入时(操作= 1)和删除时(操作= 3)。

表日志包含以下列:旧,新,操作和日期。 在INSERT上,列为NULL,列获取值。在DELETE上,列获取值,列为NULL。

你可以在示例代码上看到这个

 ;with x as (select null old, 'A' new, 1 operation, cast('20130822 12:00:01.100' as datetime) dt
         union all 
         select null,'B', 1 , '20130822 12:00:01.700' dt
         union all
         select 'B',null, 3 , '20130822 12:00:02.100' dt
         union all
         select null,'C', 1 , '20130822 12:00:05.700' dt
         union all
         select 'C',null, 3 , '20130822 12:00:06.100' dt
         union all 
         select null,'B', 1 , '20130822 12:00:08.700' dt
         )

我需要得到的结果应该是这样的:

OLD     NEW      TIME
        A        22-08-2013 12:00:01
A|      A|B      22-08-2013 12:00:01
A|B     A|B|C    22-08-2013 12:00:02
A|B|C   A|C      22-08-2013 12:00:05
A|C     A        22-08-2013 12:00:06
A       A|B      22-08-2013 12:00:08

我试图通过 for xml path 运行它,但仍然没有得到结果。 此外,没有循环是可能的。我需要获得一个查询,可以加入另一个查询。

正如我所看到的,在这里我需要检查由于操作类型和应用时间引起的范围。 可能有人有关于如何处理的建议吗? 非常感谢!

1 个答案:

答案 0 :(得分:0)

这个查询并不容易,但可行。

;with x(old, new, operation, dt) as (
    select null, 'A',  1, cast('20130822 12:00:01.100' as datetime) union all
    select null, 'B',  1, '20130822 12:00:01.700' dt union all
    select 'B',  null, 3, '20130822 12:00:02.100' dt union all
    select null, 'C',  1, '20130822 12:00:05.700' dt union all
    select 'C',  null, 3, '20130822 12:00:06.100' dt union all
    select null, 'B',  1, '20130822 12:00:08.700' dt
), y as (
    select x1.dt, isnull(x2.new, x2.old) u
    from x x1
    inner join x x2 on x1.dt >= x2.dt
    group by x1.dt, isnull(x2.new, x2.old)
    having sum((x2.operation - 2) * (-1)) > 0
)

select min(case i when 1 then new end) old
    , min(case i when 0 then new end) new
    , min(case i when 0 then dt end) dt
from (
    select distinct dt
        , dense_rank() over(order by dt) num
        , stuff ( (
            select '|' + u
            from y y2
            where y1.dt = y2.dt
            for xml path('')
        ), 1, 1, '') new
    from y y1
) t
cross join (values(0),(1))i(i)
group by num+i
having min(case i when 0 then dt end) is not null
order by dt