使用T-SQL

时间:2016-02-08 15:23:47

标签: sql sql-server tsql

我需要在两个值中的任何一个上加入一个表。我可以通过联接中的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。正如我所说的,这段代码可行,并且可以满足我的需要,但我想尝试用基于集合的操作替换它。

1 个答案:

答案 0 :(得分:0)

这个脚本没有循环/游标。它会创建两个对加速查询非常重要的索引:t_phone_indt_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 |
+-----+---------+