如何遍历表中的每一行并更新列?

时间:2017-10-03 20:01:30

标签: sql sql-server iteration common-table-expression row-number

我希望针对客户端更新任何重复的字符串,并通过在其末尾附加数字使其唯一。以下只是我所拥有的一些例子。

|Id|ClientId|String|
|1 |123     |Apple |
|2 |123     |Apple |
|3 |123     |Orange|
|4 |222     |Grapes|
|5 |222     |Grapes|

由于数据的性质,我不得不使用Row_Number()(我是新手)来实现以下结果。我的问题是如何迭代下表并为每个具有重复字符串的客户端附加一个数字,以便它们都是唯一的。

|Id|ClientId|String|RowId|
|1 |123     |Apple |1    |
|2 |123     |Apple |2    |
|3 |123     |Orange|3    |
|4 |222     |Grapes|1    |
|5 |222     |Grapes|2    |

我希望最终结果看起来像

|Id|ClientId|String   |RowId|
|1 |123     |Apple 1  |1    |
|2 |123     |Apple 2  |2    |
|3 |123     |Orange   |3    |
|4 |222     |Grapes 1 |1    |
|5 |222     |Grapes 2 |2    |

如果有帮助,那么我的sql:

patternsWithNumbers AS
(
    Select row_number() over (partition by ClientId + String order by Id asc) AS RowId,
            id,
            t1.*
    from tableName t
    inner join table 2 t2 on t2.ClientId = t1.ClientId and t2.String = t1.String
)

3 个答案:

答案 0 :(得分:1)

您可以在下面的CTE中使用您的查询:

; with cte as 
( select id,clientid,string,
row_number() over(partition by clientid, string order by id asc) r
from tbl)


select 
    c1.id,
    c1.Clientid, 
    CONCAT(c1.String, case when c2.id is not null then cast(c1.r as varchar(100)) else null end),
    c1.r
from cte c1 
left join cte c2
on c2.r>1
and c1.string=c2.string 
and c1.clientid=c2.clientid
order by id asc

see working demo

答案 1 :(得分:0)

以下查询计算rowid

  select t.*,
         (string +
          (case when count(*) over (partition by clientid, string) > 1
                then cast(row_number() over (partition by clientid, string order by id) as varchar(255))
                else 0
           end)
         ) as new_string,
         row_number() over (partition by clientid, string order by id) as rowid
  from t

使用可更新的CTE更改表:

with toupdate as (
      select t.*,
             row_number() over (partition by clientid, string order by id) as new_rowid,
             count(*) over (partition by clientid, string) as cnt
      from t
     )
update toupdate
    set rowid = new_rowid,
        string = string + cast(new_rowid as varchar(255))
    where cnt > 1;

答案 2 :(得分:0)

我会略微修改戈登的答案,以便首先只更改产品名称:

UPDATE t
SET
string = string + ' ' + CAST(t2.item_id AS VARCHAR(255))
FROM
(SELECT t.id,
ROW_NUMBER() OVER (PARTITION BY clientid, string ORDER BY id) AS item_id,
COUNT(*) OVER (PARTITION BY clientid, string) AS item_count
FROM t)
t2 
INNER JOIN t
ON t.id = t2.id
WHERE t2.item_count > 1

然后很容易只为客户端添加项目编号(当然在现实生活中你可能还有order_id或类似的东西,这需要包含在这两个查询中?):

UPDATE t
SET
RowId = row_id
FROM
(SELECT t.id,
ROW_NUMBER() OVER (PARTITION BY clientid ORDER BY id) AS row_id
FROM t)
t2 
INNER JOIN t
ON t.id = t2.id