2011-01-25 8 views
0

を使用せずに、別のテーブルのマッピング私は私がする必要がどのような構造TSQL - カーソル

create table Doc(
    id     int identity(1, 1) primary key, 
    DocumentStartValue varchar(100) 
) 
create Metadata (
    DocumentValue  varchar(100), 
    StartDesignation char(1), 
    PageNumber   int 
) 
GO 

Doc contains 
    id  DocumentStartValue 
    1000 ID-1 
    1100 ID-5 
    2000 ID-8 
    3000 ID-9 

Metadata contains 
    Documentvalue StartDesignation PageNumber 
    ID-1   D     0 
    ID-2   NULL    1 
    ID-3   NULL    2 
    ID-4   NULL    3 
    ID-5   D     0 
    ID-6   NULL    1 
    ID-7   NULL    2 
    ID-8   D     0 
    ID-9   D     0 

次を持つテーブルを持っているが

をDoc.idするMetadata.DocumentValuesをマッピングすることですので、私は必要な結果があります何かのように

id  DocumentValue PageNumber 
1000 ID-1   0 
1000 ID-2   1 
1000 ID-3   2 
1000 ID-4   3 
1100 ID-5   0 
1100 ID-6   1 
1100 ID-7   2 
2000 ID-8   0 
3000 ID-9   0 

カーソルを使用せずに達成できますか?

+1

マイスター - かなり醜いです。暴力団にうわー。 – JonH

+0

はい。しかし、それは私が提供されたデータです...残念ながら... – Sung

答えて

1

何かのような、申し訳ありませんが

;WITH RowList AS 
( --assign RowNums to each row... 
    SELECT 
     ROW_NUMBER() OVER (ORDER BY id) AS RowNum, 
     id, DocumentStartValue 
    FROM 
     doc 
), RowPairs AS 
( --this allows us to pair a row with the previous rows to create ranges 
    SELECT 
     R.DocumentStartValue AS Start, R.id, 
     R1.DocumentStartValue AS End 
    FROM 
     RowList R JOIN RowList R1 ON R.RowNum + 1 = R1.RowNum 
) 
--use ranges to join back and get the data 
SELECT 
    RP.id, M.DocumentValue, M.PageNumber 
FROM 
    RowPairs RP 
    JOIN 
    Metadata M ON RP.Start <= M.DocumentValue AND M.DocumentValue < RP.End 

編集をテストすることはできません。これは、ID-x値マッチングに依存し、昇順であることができることを前提としています。もしそうなら、StartDesignationが冗長/不必要であるとドクテーブルと競合する可能性がありDocumentStartValue

+0

最後のレコードがあなたのクエリから表示されない部分を微調整しました – Sung

1

with rm as 
(
    select DocumentValue 
    ,PageNumber 
    ,case when StartDesignation = 'D' then 1 else 0 end as IsStart 
    ,row_number() over (order by DocumentValue) as RowNumber 
    from Metadata 
) 
,gm as 
(
    select 
    DocumentValue as DocumentGroup 
    ,DocumentValue 
    ,PageNumber 
    ,RowNumber 
    from rm 
    where RowNumber = 1 

    union all 

    select 
    case when rm.IsStart = 1 then rm.DocumentValue else gm.DocumentGroup end 
    ,rm.DocumentValue 
    ,rm.PageNumber 
    ,rm.RowNumber 
    from gm 
    inner join rm on rm.RowNumber = (gm.RowNumber + 1) 
) 
select d.id, gm.DocumentValue, gm.PageNumber 
from Doc d 
inner join gm on d.DocumentStartValue = gm.DocumentGroup 

上記のクエリを使用してみてください(多分あなたもoption (maxrecursion ...)を追加する必要があります)とメタデータ・テーブルにDocumentValueにインデックスを追加します。また、それは可能です - それは、挿入するMetadatの行に適切なグループを保存する方が良いでしょう。

UPD:私はそれをテストし、私の質問ではエラーを修正しましたが、それはうまく動作せず、最初の質問と同じ結果が得られます。

UPD2:そしてインデックスを推奨:


create clustered index IX_Metadata on Metadata (DocumentValue) 
create nonclustered index IX_Doc_StartValue on Doc (DocumentStartValue)