さて、いくつか試してみたところ、次のことがわかりました。
DECLARE @mod int; SET @mod=1;
DECLARE @newgrp int; SET @newgrp=1;
CREATE TABLE tbl([x1] varchar(4), [y1] int, [x2] varchar(4), [y2] int);
INSERT INTO tbl
    ([x1], [y1], [x2], [y2])
          SELECT 'A001', 1, 'B001', 2  -- modified input to create chained equalities:
UNION ALL SELECT 'B001', 2, 'B002', 2  -- --> replaced A001 1 by B001 2
UNION ALL SELECT 'A002', 2, 'B002', 1  
UNION ALL SELECT 'C001', 2, 'B003', 3
UNION ALL SELECT 'C002', 1, 'B003', 3;
SELECT  x,y,0 grp INTO tmp FROM (
 SELECT x1 x,y1 y FROM tbl union SELECT x2 x, y2 y FROM tbl ) t;
-- set first seed: grp=1 on first ID only ...
UPDATE TOP(1) tmp SET grp=1;
-- now iteratively populate the tmp table 
WHILE @newgrp>0                         -- for each group
BEGIN 
 WHILE @mod>0 
  BEGIN                          -- in case of chained equalities
   UPDATE t2 SET grp=tmp.grp FROM tmp 
   INNER JOIN ( SELECT x1,x2 FROM tbl 
          UNION SELECT x2,x1 FROM tbl ) -- do group assignments in both directions!
              tt     ON tt.x1 = tmp.x AND tmp.grp>0
   INNER JOIN tmp t2 ON  t2.x = x2 AND t2.grp=0
   SET @mod=@@ROWCOUNT;
  END 
 -- OK, move on to the next group and then repeat the game ...
 UPDATE TOP(1) tmp SET grp=(SELECT MAX(grp) FROM tmp)+1 WHERE grp=0
 SELECT @newgrp=@@ROWCOUNT, @mod=1;
END
-- show the result
SELECT * FROM tmp
結果:
x    y   grp
---- --- ---
A001 1   1
A002 2   1
B001 2   1
B002 2   1
B003 3   2
C001 2   2
C002 1   2
推奨されるサンプル スクリプトは、列 y が比較に関連していないことを前提としています (サンプル データには、各 x 値に対して正確に 1 つの y 値があります)。もちろん、必要に応じて y 列を比較プロセスに含めることもできます。
編集:
Et violá (比較には y 列も含まれるようになりました):
そして ...ここにSQLfiddleがあります (最初にセミコロンを入れすぎました - 愚かな私)!
CREATE TABLE tbl([x1] varchar(4), [y1] int, [x2] varchar(4), [y2] int);
INSERT INTO tbl
    (x1, y1, x2, y2)
          SELECT 'A001', 1, 'B001', 2
UNION ALL SELECT 'A001', 1, 'B002', 2
UNION ALL SELECT 'A002', 2, 'A001', 1
UNION ALL SELECT 'D001', 3, 'B003', 3
UNION ALL SELECT 'D003', 1, 'D001', 3
UNION ALL SELECT 'D001', 1, 'A001', 1
UNION ALL SELECT 'C001', 2, 'B003', 3
UNION ALL SELECT 'C002', 1, 'B003', 3
-- start of processing ...
SELECT  x,y,0 grp INTO tmp FROM (
 SELECT x1 x,y1 y FROM tbl union SELECT x2 x, y2 y FROM tbl ) t;
DECLARE @mod int
SET @mod=1
DECLARE @newgrp int 
SET @newgrp=1
UPDATE TOP(1) tmp SET grp=1  -- set first grp-label (seed)
-- now iteratively populate the tmp table 
WHILE @newgrp>0                         -- for each group
BEGIN 
 WHILE @mod>0                           -- in case of chained equalities
 BEGIN
   UPDATE t2 SET grp=tmp.grp FROM tmp 
   INNER JOIN ( SELECT x1,y1,x2,y2 FROM tbl 
          UNION SELECT x2,y2,x1,y1 FROM tbl ) -- do group assignments in both directions!
              tt     ON tt.x1 = tmp.x AND tt.y1 = tmp.y AND tmp.grp>0
   INNER JOIN tmp t2 ON  t2.x = tt.x2 AND  t2.y = tt.y2 AND t2.grp=0
   SET @mod=@@ROWCOUNT
 -- OK, move on to the next group and then repeat the game ...
 END
 UPDATE TOP(1) tmp SET grp=(SELECT MAX(grp) FROM tmp)+1 WHERE grp=0
 SELECT @newgrp=@@ROWCOUNT, @mod=1
END
-- show the result
SELECT * FROM tmp
-- and drop tmp again
DROP TABLE tmp
また、いくつかのサンプル データを追加して、チェーンされた等価性( 'D001' 3='B003' 3と
'D003' 1= ) を示し、異なる y 値 (と)'D001' 3を持つケースを作成しました。最初は @@ROWCOUNT の内容に十分な注意を払っていなかったので、ループに頭が痛くなりました...今ではまた動作するはずです!'D001',1'D001' 3while
チェーン化された等価ケース (再帰) が、このクエリの主な問題でした。そうでない場合は、すべてを単一のステートメントで実行できます。@Roman Pekar を参照してください)。
私の(拡張された)例の結果:
x       y    grp
------  ---  ----
A001    1    1
A002    2    1
B001    2    1
B002    2    1
B003    3    2
C001    2    2
C002    1    2
D001    1    1
D001    3    2
D003    1    2