Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server T-sql在字段更改时重置行号_Sql Server_Tsql_Sql Server 2005_Reset_Row Number - Fatal编程技术网

Sql server T-sql在字段更改时重置行号

Sql server T-sql在字段更改时重置行号,sql-server,tsql,sql-server-2005,reset,row-number,Sql Server,Tsql,Sql Server 2005,Reset,Row Number,与我最近的一篇文章“t-sql sequential duration”类似,但并不完全相同,我想根据x列(在我的例子中是“who”列)中的更改重置行号 下面是第一个返回原始(ish)数据小样本的查询: 第二步是添加行号(我在第一次查询中没有这样做,因为使用了DISTINCT这个词);所以 下一步是我遇到的问题:目标是在“who”列中的值每次更改时将RowID重置为1。下面的代码得到了一个“几乎就在那里”的结果(应该注意的是,我从某个地方偷了/借用了这段代码,但现在我找不到该网站): 预期结果:

与我最近的一篇文章“t-sql sequential duration”类似,但并不完全相同,我想根据x列(在我的例子中是“who”列)中的更改重置行号

下面是第一个返回原始(ish)数据小样本的查询:

第二步是添加行号(我在第一次查询中没有这样做,因为使用了DISTINCT这个词);所以

下一步是我遇到的问题:目标是在“who”列中的值每次更改时将RowID重置为1。下面的代码得到了一个“几乎就在那里”的结果(应该注意的是,我从某个地方偷了/借用了这段代码,但现在我找不到该网站):

预期结果:

Row custno      moddate                     who
1   581827      2012-11-08 08:38:00.000     EMSZC14
2   581827      2012-11-08 08:41:10.000     EMSZC14
3   581827      2012-11-08 08:53:46.000     EMSZC14
4   581827      2012-11-08 08:57:04.000     EMSZC14
5   581827      2012-11-08 08:58:35.000     EMSZC14
6   581827      2012-11-08 08:59:13.000     EMSZC14
7   581827      2012-11-08 09:00:06.000     EMSZC14
1   581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1 
2   581827      2012-11-08 09:05:04.000     EMSZC49
3   581827      2012-11-08 09:06:32.000     EMSZC49
4   581827      2012-11-08 09:12:03.000     EMSZC49
5   581827      2012-11-08 09:12:38.000     EMSZC49
6   581827      2012-11-08 09:14:18.000     EMSZC49
1   581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1
感谢您的帮助。

请不要:

PARTITION BY custno ORDER BY custno, moddate, who)
尝试:


我能想到的唯一解决方案是使用游标(ugh)并经历RBAR过程。这不是一个优雅的解决方案,因为光标必须读取超过1m行的数据。Bummer.

如果您使用的是SQL Server 2012,则可以使用将值与前一行进行比较,并可以使用和记录更改

with C1 as
(
  select custno,
         moddate,
         who,
         lag(who) over(order by moddate) as lag_who
  from chr
),
C2 as
(
  select custno,
         moddate,
         who,
         sum(case when who = lag_who then 0 else 1 end) 
            over(order by moddate rows unbounded preceding) as change 
  from C1
)
select row_number() over(partition by change order by moddate) as RowID,
       custno,
       moddate,
       who
from C2

更新:

SQL Server 2005的版本。它使用递归CTE和临时表作为需要迭代的数据的中间存储

create table #tmp
(
  id int primary key,
  custno int not null,
  moddate datetime not null,
  who varchar(10) not null
);

insert into #tmp(id, custno, moddate, who)
select row_number() over(order by moddate),
       custno,
       moddate,
       who
from chr;

with C as
(
  select 1 as rowid,
         T.id,
         T.custno,
         T.moddate,
         T.who,
         cast(null as varchar(10)) as lag_who
  from #tmp as T
  where T.id = 1
  union all
  select case when T.who = C.who then C.rowid + 1 else 1 end,
         T.id,
         T.custno,
         T.moddate,
         T.who,
         C.who
  from #tmp as T
    inner join C
      on T.id = C.id + 1
)
select rowid,
       custno,
       moddate,
       who
from C
option (maxrecursion 0);

drop table #tmp;

我使用Rank()成功解决了这个问题:


这将返回您想要的结果。我发现这篇文章试图解决同样的问题

已经尝试过了(它似乎应该可以工作,不是吗?),但它仍然返回相同的结果集,最后一行号为14。不过,还是要不断地向我抛主意。我确信我只是错过了一些简单的步骤。不幸的是,我们仍在运行2005年,计划下个月升级到2008R2。滞后函数将是这个问题的一个干净的解决方案。感谢您让我注意到这一点……这只是迁移到SQL Server 2012的另一个理由。非常酷的解决方案。我唯一关心的(事实上并没有发现)是在maxrecursion中使用0。这可能会导致一个无限循环,但在考虑我的数据结构时,可能不会考虑我得到的数据。非常感谢。这个滞后函数正是我需要的!非常感谢。
WITH c1 AS (
        SELECT      DISTINCT chr.custno,
                    CAST(LEFT(CONVERT( VARCHAR(20),chr.moddate,112),10)+ ' ' + chr.modtime AS DATETIME)as moddate,
                    chr.who
        FROM        <TABLE> chr 
        WHERE       chr.custno = 581827
                    AND LEFT(chr.who, 5) = 'EMSZC'
                    AND chr.[description] NOT LIKE 'Recalled and viewed this customer'
        )
, c1a AS    (
            SELECT  ROW_NUMBER() OVER (PARTITION BY custno ORDER BY custno, moddate, who) AS RowID, custno, moddate, who
            FROM    c1
            )

SELECT  x.RowID - y.MinID + 1 AS Row,
        x.custno, x.Touch, x.moddate, x.who      
FROM    (
            SELECT  custno, who, MIN(RowID) AS MinID
            FROM    c1a
            GROUP BY custno, who
        ) AS y
        INNER JOIN c1a x ON x.custno = y.custno AND x.who = y.who
Row custno      moddate                    who
1   581827      2012-11-08 08:38:00.000     EMSZC14
2   581827      2012-11-08 08:41:10.000     EMSZC14
3   581827      2012-11-08 08:53:46.000     EMSZC14
4   581827      2012-11-08 08:57:04.000     EMSZC14
5   581827      2012-11-08 08:58:35.000     EMSZC14
6   581827      2012-11-08 08:59:13.000     EMSZC14
7   581827      2012-11-08 09:00:06.000     EMSZC14
1   581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1 (Hooray! It worked!)
2   581827      2012-11-08 09:05:04.000     EMSZC49
3   581827      2012-11-08 09:06:32.000     EMSZC49
4   581827      2012-11-08 09:12:03.000     EMSZC49
5   581827      2012-11-08 09:12:38.000     EMSZC49
6   581827      2012-11-08 09:14:18.000     EMSZC49
14  581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1 (Crappies.)
Row custno      moddate                     who
1   581827      2012-11-08 08:38:00.000     EMSZC14
2   581827      2012-11-08 08:41:10.000     EMSZC14
3   581827      2012-11-08 08:53:46.000     EMSZC14
4   581827      2012-11-08 08:57:04.000     EMSZC14
5   581827      2012-11-08 08:58:35.000     EMSZC14
6   581827      2012-11-08 08:59:13.000     EMSZC14
7   581827      2012-11-08 09:00:06.000     EMSZC14
1   581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1 
2   581827      2012-11-08 09:05:04.000     EMSZC49
3   581827      2012-11-08 09:06:32.000     EMSZC49
4   581827      2012-11-08 09:12:03.000     EMSZC49
5   581827      2012-11-08 09:12:38.000     EMSZC49
6   581827      2012-11-08 09:14:18.000     EMSZC49
1   581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1
PARTITION BY custno ORDER BY custno, moddate, who)
PARTITION BY custno, who ORDER BY custno, moddate)
with C1 as
(
  select custno,
         moddate,
         who,
         lag(who) over(order by moddate) as lag_who
  from chr
),
C2 as
(
  select custno,
         moddate,
         who,
         sum(case when who = lag_who then 0 else 1 end) 
            over(order by moddate rows unbounded preceding) as change 
  from C1
)
select row_number() over(partition by change order by moddate) as RowID,
       custno,
       moddate,
       who
from C2
create table #tmp
(
  id int primary key,
  custno int not null,
  moddate datetime not null,
  who varchar(10) not null
);

insert into #tmp(id, custno, moddate, who)
select row_number() over(order by moddate),
       custno,
       moddate,
       who
from chr;

with C as
(
  select 1 as rowid,
         T.id,
         T.custno,
         T.moddate,
         T.who,
         cast(null as varchar(10)) as lag_who
  from #tmp as T
  where T.id = 1
  union all
  select case when T.who = C.who then C.rowid + 1 else 1 end,
         T.id,
         T.custno,
         T.moddate,
         T.who,
         C.who
  from #tmp as T
    inner join C
      on T.id = C.id + 1
)
select rowid,
       custno,
       moddate,
       who
from C
option (maxrecursion 0);

drop table #tmp;
SELECT RANK() OVER (PARTITION BY who ORDER BY custno, moddate) AS RANK