我需要在两个值中的任何一个上加入一个表。我可以通过联接中的OR
轻松完成此操作。但是,我正在尝试创建一个表来存放这些数据,以便在我每天添加新记录时更容易。我想创建一个表来保存这些数据,并为每个结果保留一个唯一的值。
我在下面有一个工作示例,但它使用while
循环并且非常慢。我想将此转换为基于集合的操作,但不断缩短。
表@t
是数据的来源。表@hh
是保存唯一值(hhid
)的新表。
示例:
declare @t table (appid int, phone varchar(10), bcn varchar(10));
declare @hh table (bcn varchar(10), hhid int default(null));
insert @t
select 1, '1115551212','1'
union select 2, '1115551212','1'
union select 3, '1115551212','2'
union select 4, '9995551212','2'
union select 5, '8885551212','3'
union select 6, '1115551212','4'
union select 7, '1115551212','5'
union select 8, '7775551212','1'
union select 9, '7785551212','6'
union select 10, '7795551212','6'
insert @hh select distinct bcn,null from @t;
DECLARE @hhid int = -1;
DECLARE @bcn varchar(10);
SELECT TOP(1) @bcn = bcn FROM @hh WHERE hhid is null;
SELECT @hhid = ISNULL((SELECT MAX(isnull(hhid,-1)) FROM @hh),-1);
if @hhid = -1
SET @hhid = 4999999;
WHILE @bcn is not null
BEGIN
SET @hhid += 1;
UPDATE @hh SET hhid = @hhid WHERE bcn in (
select distinct t2.bcn
FROM @hh h
JOIN @t t on h.bcn = t.bcn
left join @t t2 on t.phone = t2.phone
WHERE h.bcn = @bcn and t.phone <> '');
SET @bcn = null;
SELECT top(1) @bcn = bcn from @hh where hhid is null;
END
select * from @hh
编辑: 预期结果(由代码返回):
BCN HHID 1 5000000 2 5000000 3 5000001 4 5000000 5 5000000 6 5000002
从输出中,您可以看到共享BCN或PHONE值的所有记录都获得相同的HHID,而那些不与其他人共享任何共同点的记录会获得自己的唯一ID。正如我所说的,这段代码可行,并且可以满足我的需要,但我想尝试用基于集合的操作替换它。
答案 0 :(得分:0)
这个脚本没有循环/游标。它会创建两个对加速查询非常重要的索引:t_phone_ind
和t_bcn_ind
。您可以检查实际执行计划,您将看到它们都被用于加速查询。
CREATE TABLE #t(appid INT PRIMARY KEY, phone VARCHAR(10), bcn VARCHAR(10));
CREATE NONCLUSTERED INDEX t_phone_ind ON #t(phone,bcn); -- for bcn->MIN(phone)
CREATE NONCLUSTERED INDEX t_bcn_ind ON #t(bcn,phone); -- for phone->MIN(bcn)
insert #t(appid,phone,bcn)
select 1, '1115551212','1'
union select 2, '1115551212','1'
union select 3, '1115551212','2'
union select 4, '9995551212','2'
union select 5, '8885551212','3'
union select 6, '1115551212','4'
union select 7, '1115551212','5'
union select 8, '7775551212','1'
union select 9, '7785551212','6'
union select 10, '7795551212','6';
;WITH cte1 AS (
SELECT bcn,MIN(phone) AS phone FROM #t GROUP BY bcn
),
cte2 AS (
SELECT phone,MIN(bcn) AS bcn FROM #t GROUP BY phone
)
SELECT
cte1.bcn,
hhid=4999999+DENSE_RANK() OVER (ORDER BY cte2.bcn)
FROM
cte1
LEFT JOIN cte2 ON
cte2.phone=cte1.phone
ORDER BY
cte1.bcn;
DROP TABLE #t;
结果:
+-----+---------+
| bcn | hhid |
+-----+---------+
| 1 | 5000000 |
| 2 | 5000000 |
| 3 | 5000001 |
| 4 | 5000000 |
| 5 | 5000000 |
| 6 | 5000002 |
+-----+---------+