Tsql 创建相关列的集群

Tsql 创建相关列的集群,tsql,Tsql,我有一个名为Stores的表,其中包含列: StoreCode NVARCHAR(10), OldStoreCode NVARCHAR(10) 以下是我的数据示例: | StoreCode | OldStoreCode | |-----------|--------------| | A | B | | B | A | | D | E | | E | F

我有一个名为Stores的表,其中包含列:

StoreCode    NVARCHAR(10),
OldStoreCode NVARCHAR(10)
以下是我的数据示例:

| StoreCode | OldStoreCode |
|-----------|--------------|
| A         | B            |
| B         | A            |
| D         | E            |
| E         | F            |
| M         | K            |
| J         | K            |
| K         | L            |
|-----------|--------------|
我想创建相关商店的集群。关联存储表示StoreCodes和OldStoreCodes之间存在单向关系

预期结果表:

| StoreCode | ClusterId |
|-----------|-----------|
| A         | 1         |
| B         | 1         |
| D         | 2         |
| E         | 2         |
| F         | 2         |
| M         | 3         |
| K         | 3         |
| J         | 3         |
| L         | 3         |
|-----------|-----------|
没有最大跳数。可能有一个存储代码a,它有一个OldStoreCode B,它有一个OldStoreCode C,它有一个OldStoreCode D等等

我如何才能像这样对存储进行群集?

这应该可以做到:

样本数据:

IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
    BEGIN
       DROP TABLE #Temp1;
    END;

CREATE TABLE #Temp1(StoreCode    NVARCHAR(10)
               , OldStoreCode NVARCHAR(10));

INSERT INTO       #Temp1(StoreCode
                   , OldStoreCode)
VALUES
      ('A'
     , 'B'),
      ('B'
     , 'A'),
      ('D'
     , 'E'),
      ('E'
     , 'F'),
      ('M'
     , 'K'),
      ('J'
     , 'K'),
      ('K'
     , 'L');
查询:

;WITH A -- get all distinct new and old storecodes
    AS (
    SELECT StoreCode
    FROM     #Temp1
    UNION
    SELECT OldStoreCode
    FROM   #Temp1),
    B -- give a unique number id to each store code
    AS (SELECT rn = RANK() OVER(ORDER BY StoreCode)
            , StoreCode
        FROM   A),
    C -- combine the store codes and the unique number id's  in one table
    AS (SELECT b2.rn AS StoreCodeID
            , t.StoreCode
            , b1.rn AS OldStoreCodeId
            , t.OldStoreCode
        FROM   #Temp1 AS t
             LEFT OUTER JOIN B AS b1 ON t.OldStoreCode = b1.StoreCode
             LEFT OUTER JOIN B AS b2 ON t.StoreCode = b2.StoreCode),
    D -- assign a row number for each entry in the data set
    AS (SELECT rn = RANK() OVER(ORDER BY StoreCode)
            , *
        FROM   C),
    E -- derive first and last store in the path
    AS (SELECT FirstStore = d2.StoreCode
            , LastStore = d1.OldStoreCode
            , GroupID = d1.OldStoreCodeId
        FROM   D AS d1
             RIGHT OUTER JOIN D AS d2 ON d1.StoreCodeID = d2.OldStoreCodeId
                                    AND d1.rn - 1 = d2.rn
        WHERE  d1.OldStoreCode IS NOT NULL) ,
    F -- get the stores wich led to the last store with one hop
    AS  (SELECT C.StoreCode
            , E.GroupID
        FROM   E
             INNER JOIN C ON E.LastStore = C.OldStoreCode)

     -- combine to get the full grouping
     SELECT A.StoreCode, ClusterID = DENSE_RANK() OVER (ORDER BY A.GroupID)  FROM (
    SELECT C.StoreCode,F.GroupID FROM C INNER JOIN F ON C.OldStoreCode = F.StoreCode 
    UNION 
    SELECT * FROM F
    UNION 
    SELECT E.LastStore,E.GroupID FROM E) AS A ORDER BY StoreCode, ClusterID
结果:

试着这样做:

编辑:由OP根据注释进行更改 结果

ID  Val
1   A
1   B
3   D
3   E
3   F
5   J
5   K
5   L
5   M

请解释一下相关存储的逻辑。我不知道您需要什么…从示例中看,您似乎正在将商店与OldStore关联,但将任何OldStore关联到另一个OldStore M->K,K->L将M关联到L。您确定这是目的吗?@Shnugo如果其中一个在StoreCode列中,另一个在OldStoreCode列中,则两个商店是相关的,在一个record@Anthony我故意以这种情况为例。考虑到关系M->K,J->K,K->L,我需要说,商店M,K,J,L形成了一个集群。你能不能更具建设性地解释一下为什么投反对票,这样我才能改进?嗨,我没有投反对票,也不知道为什么+1从我这边我对您的解决方案进行了以下添加,并达到了预期的结果。我对您的解决方案进行了以下添加,并达到了预期的结果。@ekremsekerci,抱歉,没有看到您的添加内容。。。很高兴看到这对你有用。如果问题解决了,在验收单上打勾是很好的。快乐编码!我为您的解决方案添加了以下内容,并达到了预期的效果。使结果表成为名为ClusterKeys的CTE:clusterId作为选择ClusterKey,MINID作为ID从ClusterKeys组按ClusterKey选择r.ID,r.Val从clusterId中选择c.ID=r的内部联接相关r。ID@ekremsekerci,是的,多一个CTE将允许您轻松地使用派生表。
ID  Val
1   A
1   B
3   D
3   E
3   F
5   J
5   K
5   L
5   M