如何遍历表并在一个字段中查找具有相同值的相邻行,并在SQL中有条件地更新另一列?

时间:2013-03-04 16:45:22

标签: sql sql-server recursion

我有一个表有一个名为'group_quartile'的表,它使用sql ntile()函数根据活动得分计算每个客户所处的四分位数。然而,使用这个ntile(0函数,我发现有一些客户具有相同的活动分数但是处于不同的四分位数。我需要修改'group-quartile'列以使所有具有相同活动分数的客户位于同一group_quartile中。

表值的视图:

Customer_id  Product Activity_Score Group_Quartile
 CH002          T         2328                 1
 CR001          T         268                  1
 CN001          T         178                  1
 MS006          T         45                   2
 ST001          T         21                   2
 CH001          T         0                    2
 CX001          T         0                    3
 KH001          T         0                    3
 MH002          T         0                    4
 SJ003          T         0                    4
 CN001          S         439                  1
 AC002          S         177                  1
 SC001          S         91                   2
 PV001          S         69                   3
 TS001          S         0                    4

我使用了CTE表达但它没有用。  我的查询仅更新(来自上面的示例):

 CX001          T         0                    3     

修改为

 CX001          T         0                    2

因此,仅检查第一个重复活动分数,并将该行的group_quartile更新为2。  我还需要更新以下所有行。

 CX001          T         0                    3
 KH001          T         0                    3
 MH002          T         0                    4
 SJ003          T         0                    4

我不能使用DENSE_RANK()而不是四分位来隔离记录,因为在大约4个季度内安排每个产品的客户是业务要求。 根据我的理解,我需要遍历表格 -

  1. 查找与其前身具有相同活动分数和相同产品但具有不同group_quartile的行
  2. 将所选行的group_quartile更新为其前任的四分位值
  3. 然后通过更新的表循环以查找具有上述条件的任何行,并以类似方式更新该行。
  4. 循环继续,直到所有具有相同活动分数的行(对于同一产品)放在同一个group_quartile中。
  5. - 这是我正在进行的表格结构:



    CREATE TABLE #custs

    customer_id NVARCHAR(50),
    产品NVARCHAR(50),
    ACTIVITYSCORE INT,
    GROUP_QUARTILE INT,
    排名int,
    rownum int

    插入#custs    
    - 添加一列以为每行提供行号(唯一ID)     
    SELECT customer_id,PRODUCT,ACTIVITYSCORE,GROUP_QUARTILE,RANKED,     
    Row_Number()OVER(按产品分区ORDER BY activityscore desc)N     
    FROM     
    - 基于“分段”列值从父表派生的行     
    (SELECT customer_id,PRODUCT,ACTIVITYSCORE,     
    DENSE_RANK()超过(按活动分类的产品分类除外)排名,     
    NTILE(4)(按活动分类的产品分类)作为GROUP_QUARTILE     
    FROM #parent_score_table WHERE(SEGMENTATION ='Large')     
    )作为临时     
    按产品订购


    我用来实现这一目标的方法如下:


    - 查询查找活动分数与前一行相同但具有不同GRoup_Quartiel值的行。
    - 我需要使用查询来更新这一行。
    - 接下来,在这个新更新的表中查找活动分数与上一行相同但行不同的group_quartile值的任何行。
    - 继续以上述方式更新表格,直到所有具有相同活动分数的行已更新为具有相同的四分位值

    我设法只查找活动分数与前一行相同但行的Group_Quartill值不同但行不能循环查找可能与此更新行匹配的新行的行。

    选择t1.customer_id,t1.ACTIVITYSCORE,t1.PRODUCT,t1.RANKED,t1.GROUP_QUARTILE,
    t2.GROUP_QUARTILE as modified_quartile
    来自#custs t1,#custs t2
    其中(
    t1.rownum = t2.rownum + 1
    和t1.ACTIVITYSCORE = t2.ACTIVITYSCORE
    和t1.PRODUCT = t2.PRODUCT
    而不是(t1.GROUP_QUARTILE = t2.GROUP_QUARTILE))


    任何人都可以帮忙解决上面的t-sql语句吗?  干杯!

1 个答案:

答案 0 :(得分:1)

假设您已经按照上面的说明制定了基础Group_Quartile,则可以使用类似于以下内容的查询更新表格:

update a
set Group_Quartile = coalesce(topq.Group_Quartile, a.Group_Quartile)
from activityScores a
  outer apply
  (
    select top 1 Group_Quartile
    from activityScores topq
    where a.Product = topq.Product
      and a.Activity_Score = topq.Activity_Score
    order by Group_Quartile
  ) topq

SQL Fiddle with demo

评论后修改:

我认为你已经做了很多工作,让Group_Quartile正常工作。

对于表中的每一行,上面的语句将使用outer apply语句将另一行连接到它。由于top 1子句,只有一行将连接回原始表。

因此,对于每一行,我们再返回一行。额外的行将在ProductActivity_Score上匹配,并且将是Group_Quartile order by Group_Quartile最低的行。最后,我们使用最低Group_Quartile值更新原始行,以便具有相同ProductActivity_Score的每一行现在具有相同的,尽可能低的Group_Quartile

所以 SJ003 MH002 等都将与 CH001 匹配,并使用Group_Quartile值进行更新> CH001 ,即 2

解释代码很难!另一件可能有用的事情是在没有update语句的情况下查看连接:

select a.*
  , TopCustomer_id = topq.Customer_Id
  , NewGroup_Quartile = topq.Group_Quartile
from activityScores a
  outer apply
  (
    select top 1 *
    from activityScores topq
    where a.Product = topq.Product
      and a.Activity_Score = topq.Activity_Score
    order by Group_Quartile
  ) topq

SQL Fiddle without update