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

问题描述 投票:11回答:4

类似于最近发布的“ t-sql顺序持续时间”,但不完全相同,我想根据x列(在我的情况下为“ who”列)的更改来重置行号。] >

这是第一个返回少量原始数据的查询:

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'
ORDER BY    chr.custno

结果:

custno      moddate             who
581827      2012-11-08 08:38:00.000     EMSZC14
581827      2012-11-08 08:41:10.000     EMSZC14
581827      2012-11-08 08:53:46.000     EMSZC14
581827      2012-11-08 08:57:04.000     EMSZC14
581827      2012-11-08 08:58:35.000     EMSZC14
581827      2012-11-08 08:59:13.000     EMSZC14
581827      2012-11-08 09:00:06.000     EMSZC14
581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1
581827      2012-11-08 09:05:04.000     EMSZC49
581827      2012-11-08 09:06:32.000     EMSZC49
581827      2012-11-08 09:12:03.000     EMSZC49
581827      2012-11-08 09:12:38.000     EMSZC49
581827      2012-11-08 09:14:18.000     EMSZC49
581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1

第二步是添加行号(由于使用DISTINCT字,我在第一个查询中没有这样做);所以...

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'
        )

SELECT  ROW_NUMBER() OVER (PARTITION BY custno ORDER BY custno, moddate, who) AS RowID, custno, moddate, who
FROM    c1

结果:

RowID   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
8       581827      2012-11-08 09:04:39.000     EMSZC49 Reset row number to 1
9       581827      2012-11-08 09:05:04.000     EMSZC49
10      581827      2012-11-08 09:06:32.000     EMSZC49
11      581827      2012-11-08 09:12:03.000     EMSZC49
12      581827      2012-11-08 09:12:38.000     EMSZC49
13      581827      2012-11-08 09:14:18.000     EMSZC49
14      581827      2012-11-08 09:17:35.000     EMSZC14 Reset row number to 1

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

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

感谢您的协助。

类似于最近发布的“ t-sql顺序持续时间””,但不完全相同,我想根据x列(在本例中为“ who”列)的更改来重置行号。这是第一个...

sql-server tsql sql-server-2005 reset row-number
4个回答
26
投票

如果您使用的是SQL Server 2012,则可以使用LAG将值与上一行进行比较,并且可以使用SUMOVER来记录更改。

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

6
投票

我通过使用Rank()成功解决了此问题:


2
投票

而不是:


-2
投票

我能想到的唯一解决方案是使用游标(ugh)并经历RBAR过程。这不是一个很好的解决方案,因为游标必须读取超过1m的行。闷闷不乐。

© www.soinside.com 2019 - 2024. All rights reserved.