计算sql中位列的出现次数

时间:2013-10-25 10:41:25

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

如何计算sql server列中的更改,例如我有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 个答案:

答案 0 :(得分: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步:获利!

答案 1 :(得分:1)

不确定您是否想要一个既适用于2008年又适用于2012年的解决方案,但是在2012年(在2008年无效)我们确实得到了LAG()LEAD()所以在下面的查询中,SUM()的{​​{1}}将在2012年执行此操作。您必须决定如何处理第一个值(显然没有先前的值),当前状态计为改变。

[Change]

对于2008年,自我加入应产生相同的结果。

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;

答案 2 :(得分: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

答案 3 :(得分:-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