3

我的行看起来像这样:

1
0 ----> Change! This row is of interest
1 ----> Change again.
1
1
1
1
1
0 ----> Change.
1 ----> Change.

在新的 1 之前可能有一百万个零,我只想要更改(标有更改的行)。这会给我带来一个减少约 1000 万行的结果。我们支持 SQLServer 和 PostGresSQL。它按时间戳列排序。0 是系统离线标志,1 是系统在线。服务会定期报告此信息并为其添加时间戳。

有任何想法吗?编辑:还有很多其他列是确定顺序的时间戳列。0 是系统离线标志,1 是系统在线。服务会定期报告此信息并为其添加时间戳。

干杯

4

4 回答 4

5

好的。所以根据评论我们知道有时间戳列。假设这被命名为“event_when”,而 0/1 列被命名为“status”。

所以我们可以:

with x as (
    select
        *,
        lag(status) over (order by event_when) is distinct from status as interesting
    from table
)
select * from x where interesting;
于 2013-07-03T13:55:46.097 回答
2

如果您有 ID,并且它们是连续的,您可以尝试以下操作:

SELECT table1.* FROM table table1, table table2 
WHERE table1.id = table2.id- 1
AND table1.value != table2.value

如果没有看到结构的其余部分,很难说,但在上述情况下,value是包含0or的列,1并且id是主键。如果您没有 id 列,或者它们不是增量的,那么您可能需要指定更复杂的选择器,或者在此处包含更多架构。

于 2013-07-03T13:47:31.813 回答
0

我们必须知道如何找到前一行,但一般的解决方案是(我假设你的行有列 Date 并且它是唯一的)

select *
from temp as t1
    outer apply
    (
        select top 1 *
        from temp as t2
        where t2.Date < t1.Date /* or you columns */
        order by t2.Date desc /* or you columns */
    )
where t2.value <> t1.value

编辑:因为我通常在 2008 R2 SQL Server 上工作,所以我忘记了 LAG 和 LEAD 函数。因此,基于 PostgreSQL 的@depesz 答案,这里是 SQL Server 版本:

with CTE_temp as (
    select
        *,
        lag([State]) over (order by [Time]) as State_Previous
    from temp
)
select *
from CTE_temp
where State_Previous <> [State]

SQL 提琴示例

于 2013-07-03T13:52:23.667 回答
-1

选项 #1:使用 MS SQL SERVER 2008

使用时间戳排序,我们可以使用rank()函数和临时表。也可以使用 CTE 和表变量。性能是一个棘手的部分,所以如果将来要重复这三个选项,我建议测试这三个选项。我将展示两个示例:

  • 临时表(在 SQLFiddle 中尝试):

    select  rank() OVER (ORDER BY order_timestamp) as 'Rank', status into temp1 from temp
    
    select t1.status as status, case when t1.status - t2.status = 0 then 'not changed' else 'changed' end as changed
    from temp1 t1, temp1 t2 
    where t1.Rank = t2.Rank + 1
    
    drop table temp1 
    
  • CTE(在 SQLFiddle 中尝试):

    with CTE_temp as (
        select rank() OVER (ORDER BY order_timestamp) as 'Rank', * 
        from temp
    )
    select t1.status as status, case when t1.status - t2.status = 0 then 'not changed' else 'changed' end as changed
    from CTE_temp t1, CTE_temp t2 
    where t1.Rank = t2.Rank + 1
    

选项 #2:使用 MS SQL SERVER 2012

MS SQL SERVER 2012 引入leadlag( http://blog.sqlauthority.com/2011/11/15/sql-server-introduction-to-lead-and-lag-analytic-functions-introduced-in-sql-server-2012 /)。

在这种情况下,选项 #1 仍然有效,但您也可以尝试@RomanPekar 的解决方案。

更新:

基于@RomanPekar 的评论(以及某人的反对票),我不得不说临时表可以比 CTE 和表变量更好地执行,尤其是在需要大量数据时。优化器可以使用临时表中的统计信息来建立其查询计划,这可以提高性能。

同样,根据 OP 之后想要提供数据的用途(可能是更多查询),临时表仍然存在,不必执行新查询,并且在这些情况下可以使用索引来提高性能。

顺便说一句,破解我的答案并将其转换为 CTE 或表变量很容易,所以如果这是他将来会重复的操作,我建议 OP 测试这三种情况的性能。

于 2013-07-03T13:57:56.340 回答