0

我需要一个选择查询来根据订单交易表中前一行的数字创建一个新项目。

有一个顺序的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
4

3 回答 3

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
于 2013-05-21T17:17:52.547 回答
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
于 2013-05-20T17:58:12.817 回答
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]
于 2013-05-20T18:04:19.310 回答