我需要一个select查询来根据订单交易表中的前一行编号来生成新项目。
有序列LineItem
,因此ID与01,02,03等之间的差异会有所不同。我正在考虑查询中的临时表:OrderNo,ID其中ID为01到20以及用于测试LineItem的case语句以及它是否在......之间...
ID 01 2834111和ID CA800 = 2834112更多01而不是02,所以-01将是它的前缀。
我是否在正确的轨道上?这似乎是一个长期的陈述。
OrderNo LineItem ID Need to Make
----------------------------------------------------------------------
236201 2834111 01
236201 2834112 CA800 01-CA800
236201 2834113 BERRY 01-BERRY
236201 2834114 02
236201 2834115 MSIJ54 02-IJ54
236201 2834116 92-D-06 02-92-D-06
236201 2834117 BERRY 02-BERRY
236201 2834118 03
236201 2834119 SACOLBS24 03-SACOLBS24
236201 2834121 OWK32 03-OWK32
236201 2834122 04
236201 2834123 SBMRY 04-SBMRY
236201 2834124 DAWN 04-DAWN
236201 2834125 05
236201 2834126 NWM216D 05-NWM216D
236201 2834127 DAWN 05-DAWN
答案 0 :(得分:1)
如果HABO有您的要求,您可以试试这个:
SELECT
p.*, id.id + '- ' + p.id AS prefixedid
FROM
(SELECT
tbl.orderno,
tbl.lineitem,
tbl.id,
MAX(id.lineitem) AS max_id_lineitem
FROM
tbl INNER JOIN
(SELECT * FROM tbl WHERE id >='01' AND id <='20') id ON
tbl.orderno = id.orderno AND
tbl.lineitem > id.lineitem LEFT OUTER JOIN
(SELECT * FROM tbl WHERE id >='01' AND id <='20') id_fornull ON
tbl.orderno = id_fornull.orderno AND
tbl.lineitem = id_fornull.lineitem
WHERE
id_fornull.lineitem IS NULL
GROUP BY
tbl.orderno,
tbl.lineitem,
tbl.id) p INNER JOIN
(SELECT * FROM tbl WHERE id >='01' AND id <='20') id ON
p.orderno = id.orderno AND
p. max_id_lineitem = id.lineitem
答案 1 :(得分:0)
首先将关键行拉入临时表:
SELECT OrderNo, LineItem, ID
INTO #TempOrder
FROM YourOrderTable
WHERE SUBSTRING(LINEITEM, 1, 1) IN ('1','2')
AND SUBSTRING(LINEITEM, 2, 1) IN ('1','2','3','4','5','6','7','8','9','0')
AND LEN(LINEITEM) = 2
然后,如果您正在寻找特定的@LineItem:
SELECT @MaxLineItem = MAX(LineItem)
FROM #TempOrder
WHERE LineItem <= @LineItem
然后你可以查找:
SELECT @MaxLineItemID = ID
FROM #TempOrder
WHERE LineItem = @MaxLineItem
@MaxLineItem必须与@LineItem不同吗?如果是这样的话:
SELECT CASE WHEN @LineItem = @MaxLineItem THEN ID
ELSE @MaxLineItemID + ' - ' + ID END AS NewID
FROM YourOrderTable
WHERE LineItem = @LineItem
答案 2 :(得分:0)
您可能希望在Row_Number
上对OrderNo
进行分区,但这应该可以让您入门:
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]