2

如何计算sql server列中的变化,例如我有Ignition值 Ignition 1 1 0 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1

我只想计算变化,它是从 0 到 1 以使出现 1。它也可以从 1 到 0 以使出现为 1。

4

4 回答 4

2

第 1 步:根据我们的订单,使用该Row_Number()功能提供完整(完整)的数字序列

SELECT ignition
     , id
     , Row_Number() OVER (ORDER BY id ASC) As row_num
FROM   your_table

第 4 步:将其设为公用表表达式 (CTE),以便我们可以引用派生row_num

; WITH cte AS (
  SELECT ignition
       , id
       , Row_Number() OVER (ORDER BY id ASC) As row_num
  FROM   your_table
)
SELECT ignition
     , id
     , row_num
FROM   cte

第 3 步:将此表连接回与下一行/上一行匹配的自身

; WITH cte AS (
  SELECT ignition
       , id
       , Row_Number() OVER (ORDER BY id ASC) As row_num
  FROM   your_table
)
SELECT c1.ignition As c1_ignition
     , c2.ignition As c2_ignition
FROM   cte As c1
 LEFT
  JOIN cte As c2
    ON c2.row_num = c1.row_num + 1

第 4 步:过滤结果以显示值不同的结果

; WITH cte AS (
  SELECT ignition
       , id
       , Row_Number() OVER (ORDER BY id ASC) As row_num
  FROM   your_table
)
SELECT c1.ignition As c1_ignition
     , c2.ignition As c2_ignition
FROM   cte As c1
 LEFT
  JOIN cte As c2
    ON c2.row_num = c1.row_num - 1
WHERE  c1.ignition <> c2.ignition

第 5 步: ...

第6步:利润!

于 2013-10-25T11:17:49.790 回答
1

不确定您是否想要一个在 2008 年和 2012 年都适用的解决方案,因为您有两个标签,但是在 2012 年(在 2008 年不起作用)我们确实得到了LAG()LEAD()所以下面查询中的 aSUM()[Change]在 2012 年做到这一点。你必须决定如何处理第一个值(显然没有以前的值),当前状态算作变化。

SELECT [Id]
     , [Ignition]
     , LAG([Ignition]) OVER(ORDER BY [Id]) [Previous]
     , CASE WHEN LAG([Ignition]) OVER(ORDER BY [Id]) = [Ignition] THEN 0 ELSE 1 END [Change]
  FROM [dbo].[Table]
 ORDER BY Id;

对于 2008 年,自联接应该产生相同的结果。

SELECT [T1].[Id]
     , [T1].[Ignition]
     , [T2].[Ignition] [Previous]
     , CASE WHEN [T1].[Ignition] = [T2].[Ignition] THEN 0 ELSE 1 END [Change]
  FROM [dbo].[Table] [T1]
  LEFT JOIN [dbo].[Table] [T2] ON [T1].[Id] = ([T2].[Id] + 1)
 ORDER BY [T1].[Id];
于 2013-10-25T11:46:42.237 回答
0
declare @t table(id int identity(1,1), ignition bit)
insert @t values(1),(0),(1),(1)
declare @Ignition varchar(max) = ''

select @Ignition = @Ignition + cast(Ignition as char(1))
from @t order by id
select @ignition

select len(replace(replace(replace(@Ignition, '10', 'x') 
       + replace(@Ignition, '01', 'x'), 1, ''), 0, ''))

结果:

2
于 2013-10-25T11:04:54.827 回答
-2

我知道的 SQL Server 2008 最简单和最短的方法是:

with cte as (
    select
        row_number() over(partition by Ignition order by Id) as rn1,
        row_number() over(order by Id) as rn2
    from Table1
)
select count(distinct rn2 - rn1) - 1
from cte

或者,正如@MartinSmith 指出的那样:

with cte as (
    select
        row_number() over(order by Ignition, Id) as rn1,
        row_number() over(order by Id) as rn2
    from Table1
), cte2 as (
    select distinct Ignition, rn2 - rn1
    from cte
)
select count(*) - 1
from cte2

对于 SQL Server 2012,您可以使用lag()(或lead())函数:

;with cte as (
    select
        lag(Ignition) over(order by Id) as prev,
        Ignition as cur
    from Table1
)
select count(case when cur <> prev then 1 end)
from cte;

sql fiddle demo

于 2013-10-25T11:30:19.220 回答