SQL Server:任何人都可以简化这种逻辑

时间:2012-02-24 07:06:13

标签: sql sql-server sql-server-2008

我的查询如下

declare @row_id int = 2
declare @last_row_id int  =(select MAX(Row_ID) from dbo.Source)

create table #source  (
    Row_ID float null,
      [Document] [nvarchar](255) NULL,    
      [ITEMCode] [nvarchar](255) NULL,    
      [Text] [nvarchar](255) NULL)

while(@row_id<=(@last_row_id))
begin

declare @Document nvarchar(255)
declare @itemcode nvarchar(255)

select @itemcode=ITEMCode,@Document=Document from dbo.Source where Row_ID=@row_id


if ((@itemcode='' or @itemcode is null ) )
select @itemcode=ITEMCode,@Document=Document from #source where Row_ID=@row_id-1

insert into #source
select Row_ID,@Document,@itemcode,[Text]
from dbo.Source where Row_ID=@row_id

print @row_id

set @row_id= @row_id+1

end

select * from #source
drop table #source

目前我的桌子有347000行。花了一个多小时来获得最终输出。这个查询怎么能更快。有人可以帮忙吗?

要求:

来源:

  Row_ID    Document    ITEMCode     Text                   
    2      10223         20235       aaaa
    3                                    bbbb
    4                                    cccc
    5      10278         202475      xxxx
    6                                    yyyy
    7                                    yyy

输出应为:

 Row_ID  Document  ITEMCode Text    
   2       10223     20235  aaaa
   3       10223     20235  bbbb
   4       10223     20235  cccc
   5       10278    202475  xxxx
   6       10278    202475  yyyy
   7       10278    202475  yyy

2 个答案:

答案 0 :(得分:1)

您可以使用recursive CTE

WITH
  Source (Row_ID, Document, ITEMCode, Text) AS (
    SELECT 2, '10223', '20235' , 'aaaa' UNION ALL
    SELECT 3, ''     , ''      , 'bbbb' UNION ALL
    SELECT 4, ''     , ''      , 'cccc' UNION ALL
    SELECT 5, '10278', '202475', 'xxxx' UNION ALL
    SELECT 6, '10278', '202475', 'yyyy' UNION ALL
    SELECT 7, '10278', '202475', 'yyy'
  ),
  ranked AS (
    SELECT
      *,
      rnk = ROW_NUMBER() OVER (ORDER BY Row_ID)
    FROM Source
  ),
  filled AS (
    SELECT
      Row_ID,
      Document,
      ITEMCode,
      Text,
      rnk
    FROM ranked
    WHERE rnk = 1
    UNION ALL
    SELECT
      r.Row_ID,
      Document = ISNULL(NULLIF(r.Document, ''), f.Document),
      ITEMCode = ISNULL(NULLIF(r.ITEMCode, ''), f.ITEMCode),
      r.Text,
      r.rnk
    FROM ranked r
      INNER JOIN filled f ON r.rnk = f.rnk + 1
  )
SELECT
  Row_ID,
  Document,
  ITEMCode,
  Text
FROM filled

输出:

Row_ID      Document ITEMCode Text
----------- -------- -------- ----
2           10223    20235    aaaa
3           10223    20235    bbbb
4           10223    20235    cccc
5           10278    202475   xxxx
6           10278    202475   yyyy
7           10278    202475   yyy

如果DocumentITEMCode实际上是整数而不是字符串,则上述脚本可以正常工作,但通常最好更改这两行:

Document = ISNULL(NULLIF(r.Document, ''), f.Document),
ITEMCode = ISNULL(NULLIF(r.ITEMCode, ''), f.ITEMCode),
像这样:

Document = ISNULL(NULLIF(r.Document, 0), f.Document),
ITEMCode = ISNULL(NULLIF(r.ITEMCode, 0), f.ITEMCode),

答案 1 :(得分:0)

即使上面指定的查询可能有效,我在excel中编写了一个宏,我们可以快速查找,并在不到5分钟内获得输出