9

データ テーブル内の重複するエントリを結合し、それらに新しい番号を付けようとしています。

これはデータセットの例です (実行可能なコピー)

declare @tmpTable table
    (ID Varchar(1), 
     First varchar(4), 
     Last varchar(5), 
     Phone varchar(13),
     NonKeyField varchar(4))

insert into @tmpTable select 'A', 'John', 'Smith', '(555)555-1234', 'ASDF'
insert into @tmpTable select 'B', 'John', 'Smith', '(555)555-1234', 'GHJK'
insert into @tmpTable select 'C', 'Jane', 'Smith', '(555)555-1234', 'QWER'
insert into @tmpTable select 'D', 'John', 'Smith', '(555)555-1234', 'RTYU'
insert into @tmpTable select 'E', 'Bill', 'Blake', '(555)555-0000', 'BVNM'
insert into @tmpTable select 'F', 'Bill', 'Blake', '(555)555-0000', '%^&*'
insert into @tmpTable select 'G', 'John', 'Smith', '(555)555-1234', '!#RF'

select row_number() over (partition by First, Last, Phone order by ID) NewIDNum, *  
from @tmpTable order by ID

今それは私に結果を与える

NewIDNum             ID   First Last  Phone         NonKeyField
-------------------- ---- ----- ----- ------------- -----------
1                    A    John  Smith (555)555-1234 ASDF
2                    B    John  Smith (555)555-1234 GHJK
1                    C    Jane  Smith (555)555-1234 QWER
3                    D    John  Smith (555)555-1234 RTYU
1                    E    Bill  Blake (555)555-0000 BVNM
2                    F    Bill  Blake (555)555-0000 %^&*
4                    G    John  Smith (555)555-1234 !#RF

ただし、それは私が望むものとは反対ですNewIDNum。キーの新しい組み合わせが見つかるたびに、カウンターがリセットされます。同じ組み合わせのすべてに同じ ID を持たせたい。したがって、私が望むように動作していた場合、次の結果が得られます

NewIDNum             ID   First Last  Phone         NonKeyField
-------------------- ---- ----- ----- ------------- -----------
1                    A    John  Smith (555)555-1234 ASDF
1                    B    John  Smith (555)555-1234 GHJK
2                    C    Jane  Smith (555)555-1234 QWER
1                    D    John  Smith (555)555-1234 RTYU
3                    E    Bill  Blake (555)555-0000 BVNM
3                    F    Bill  Blake (555)555-0000 %^&*
1                    G    John  Smith (555)555-1234 !#RF

私が望む結果を得るための正しい方法は何ですか?


元の投稿にはこの要件を含めませんでしたNewIDNum:より多くの行が追加された場合、既存の行に対してこのクエリの後続の実行で同じ数値を生成する必要があります (注文がby は ID 列で行われます)

したがって、後日、次のことが行われた場合

insert into @tmpTable select 'H', 'John', 'Smith', '(555)555-1234', '4321'
insert into @tmpTable select 'I', 'Jake', 'Jons', '(555)555-1234', '1234'
insert into @tmpTable select 'J', 'John', 'Smith', '(555)555-1234', '2345'

正しいクエリを再度実行すると、

NewIDNum             ID   First Last  Phone         NonKeyField
-------------------- ---- ----- ----- ------------- -----------
1                    A    John  Smith (555)555-1234 ASDF
1                    B    John  Smith (555)555-1234 GHJK
2                    C    Jane  Smith (555)555-1234 QWER
1                    D    John  Smith (555)555-1234 RTYU
3                    E    Bill  Blake (555)555-0000 BVNM
3                    F    Bill  Blake (555)555-0000 %^&*
1                    G    John  Smith (555)555-1234 !#RF
1                    H    John  Smith (555)555-1234 4321
4                    I    Jake  Jons  (555)555-1234 1234
1                    J    John  Smith (555)555-1234 2345
4

4 に答える 4

8

使用できますdense_rank()

dense_rank() over (order by First, Last, Phone) as NewIDNum

あなたのコメントに応えて、同じ組み合わせIdで行のグループごとに古い列の最小値を並べ替えることができます。(First, Last, Phone)

select  *
from    (
        select  dense_rank() over (order by min_id) as new_id
        ,       *
        from    (
                select  min(id) over (
                            partition by First, Last, Phone) as min_id
                ,       *
                from    @tmpTable 
                ) as sub1
        ) as sub3
order by
        new_id
于 2012-10-02T18:15:44.163 に答える
1

@Andomarの元の回答に基づいて構築-これは更新された要件で機能します(ただし、これはうまくスケーリングされない可能性があります)

select
    DENSE_RANK() over (ORDER BY IdRank, First, Last, Phone) AS NewIDNum,
    ID,
    First,
    Last,
    Phone,
    NonKeyField
from
(
    select
        MIN(ID) OVER (PARTITION BY First, Last, Phone) as IdRank,
        *
    from
        @tmpTable
) as x
order by
    ID;
于 2012-10-02T18:36:38.253 に答える
0

出発点としてのAndomarの回答のおかげで、私はそれを自分で解決しました

select sub1.rn, tt.*
from @tmpTable tt
inner join (
    select row_number() over (order by min(ID)) as rn, first, last, phone
    from @tmpTable
    group by first, last, phone
    ) as sub1 on tt.first = sub1.first and tt.last = sub1.last and tt.phone = sub1.phone

これが生み出す

rn                   ID   First Last  Phone         NonKeyField
-------------------- ---- ----- ----- ------------- -----------
1                    A    John  Smith (555)555-1234 ASDF
1                    B    John  Smith (555)555-1234 GHJK
1                    D    John  Smith (555)555-1234 RTYU
1                    G    John  Smith (555)555-1234 !#RF
1                    H    John  Smith (555)555-1234 4321
1                    J    John  Smith (555)555-1234 2345
2                    C    Jane  Smith (555)555-1234 QWER
3                    E    Bill  Blake (555)555-0000 BVNM
3                    F    Bill  Blake (555)555-0000 %^&*
4                    I    Jake  Jons  (555)555-1234 1234

SQL 実行計画を見ると、Adnomar の回答は、私のものよりも大きなデータ セットに対してより速く実行されます。(53% の実行時間 VS 47% の実行時間は、互いに隣り合わせて実行し、「実際の実行計画を含める」をチェックした場合。

于 2012-10-02T18:42:07.587 に答える
-1

これはうまくいくはずです

select dense_rank() over (order by First, Last, Phone) NewIDNum, *  
from @tmpTable order by ID
于 2012-10-02T18:20:38.330 に答える