你可能想在OrderNo
分區Row_Number
,但這應該讓你開始:
declare @LineItems as Table (LineItem Int Identity, Id VarChar(16));
insert into @LineItems (Id) values
('01'), ('CA800'), ('BERRY'),
('02'), ('MSIJ54'), ('92-D-06'), ('BERRY');
with LineItems as (
select LineItem, Id, Row_Number() over (order by LineItem) as RN
from @LineItems
),
PrefixedLineItems as (
select LineItem, Id, Id as Prefix, Cast(NULL as VarChar(16)) as Result, RN
from LineItems
where RN = 1
union all
select LI.LineItem, LI.Id,
case when IsNumeric(LI.Id) = 1 then LI.Id else PLI.Prefix end,
case when IsNumeric(LI.Id) = 1 then NULL else Cast(PLI.Prefix + '-' + LI.Id as VarChar(16)) end, LI.RN
from PrefixedLineItems as PLI inner join
LineItems as LI on LI.RN = PLI.RN + 1
)
select LineItem, Id, Result
from PrefixedLineItems
order by LineItem
option (MaxRecursion 0)
額外的測試可以添加如果顯著ID
的值必須在01
開始,計數到20
。
編輯:好的,那個比例很差。
產生額外的樣本數據版本是:
-- Sample data.
if Object_Id('tempdb..#LineItems', N'U') is not NULL
drop table #LineItems;
create table #LineItems (LineItem Int Identity Primary Key, Id VarChar(32) not null);
insert into #LineItems (Id) values
('01'), ('CA800'), ('BERRY'),
('02'), ('MSIJ54'), ('92-D-06'), ('BERRY');
-- Generate some additional sample data.
declare @Count as Int = 1000;
while @Count > 0
begin
if Rand() < 0.1 -- Make about 10% of the entries numeric.
insert into #LineItems (Id) values (Right('0' + Cast(Floor(Rand() * 20) + 1 as VarChar(2)), 2));
else
insert into #LineItems (Id) values ('Foo ' + Cast(Rand() as VarChar(16)));
set @Count = @Count - 1;
end;
-- Time the query.
declare @Start as DateTime = SysDateTime();
with NumberedLineItems as (
select LineItem, Id, Row_Number() over (order by LineItem) as RN
from #LineItems
),
PrefixedLineItems as (
select LineItem, Id, Id as Prefix, Cast(NULL as VarChar(16)) as Result, RN
from NumberedLineItems
where RN = 1
union all
select LI.LineItem, LI.Id,
case when IsNumeric(LI.Id) = 1 then LI.Id else PLI.Prefix end,
case when IsNumeric(LI.Id) = 1 then NULL else Cast(PLI.Prefix + '-' + LI.Id as VarChar(16)) end, LI.RN
from PrefixedLineItems as PLI inner join
NumberedLineItems as LI on LI.RN = PLI.RN + 1
)
select LineItem, Id, Result
from PrefixedLineItems
order by LineItem
option (MaxRecursion 0);
select DateDiff(ms, @Start, SysDateTime()) as [Elapsed Milliseconds],
(select Count(*) from #LineItems) as [Rows];
這RBAR方法更有效地磅秤:
-- Sample data.
if Object_Id('tempdb..#LineItems', N'U') is not NULL
drop table #LineItems;
create table #LineItems (LineItem Int Identity Primary Key, Id VarChar(32) not null);
insert into #LineItems (Id) values
('01'), ('CA800'), ('BERRY'),
('02'), ('MSIJ54'), ('92-D-06'), ('BERRY');
-- Generate some additional sample data.
declare @Count as Int = 10000;
while @Count > 0
begin
if Rand() < 0.1 -- Make about 10% of the entries numeric.
insert into #LineItems (Id) values
(Right('0' + Cast(Floor(Rand() * 20) + 1 as VarChar(2)), 2))
else
insert into #LineItems (Id) values ('Foo ' + Cast(Rand() as VarChar(16)))
set @Count = @Count - 1;
end;
-- Create a fiendish thingy.
declare Plod cursor fast_forward for
select LineItem, Id
from #LineItems
order by LineItem;
declare @LineItem as Int;
declare @Id as VarChar(32);
declare @Prefix as VarChar(2)
-- Create a table to hold the results.
if Object_Id('tempdb..#PrefixedLineItems', N'U') is not NULL
drop table #PrefixedLineItems;
create table #PrefixedLineItems
(LineItem Int Primary Key, Id VarChar(32) not null, Prefix VarChar(2) null);
-- RBAR.
declare @Start as DateTime = SysDateTime();
open Plod;
fetch next from Plod into @LineItem, @Id;
while @@Fetch_Status = 0
begin
set @Prefix = case when IsNumeric(@Id) = 1 then @Id else @Prefix end;
insert into #PrefixedLineItems (LineItem, Id, Prefix) values
(@LineItem, @Id, case when IsNumeric(@Id) = 1 then NULL else @Prefix end);
fetch next from Plod into @LineItem, @Id;
end;
close Plod;
deallocate Plod;
-- That's all, folks!
select LineItem, Id, Prefix
from #PrefixedLineItems
order by LineItem;
select DateDiff(ms, @Start, SysDateTime()) as [Elapsed Milliseconds],
(select Count(*) from #LineItems) as [Rows]
讓我試着重新措辭。你想在'LineItem'順序中移動表格。當你遇到一個恰好是兩位數的「ID」值時,你希望將該值作爲前綴(帶短劃線)傳播給後續的ID,直到遇到下一個數字「ID」。這是總結嗎? – HABO
除了匹配'01'到'20'之外,是否還有其他區別像'01'的行? – criticalfix
是 - 有一個全局唯一的int列與每個ID相關聯,所以ID'01%'= 36221會更清晰,但沒有任何東西可以連接到另一個表中的值。 – user1529496