TSQL - отображение одной таблицы в другую без использования курсора - PullRequest
0 голосов
/ 25 января 2011

У меня есть таблицы со следующей структурой

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

Мне нужно сопоставить Metadata.DocumentValues ​​с Doc.id

Итак, мне нужен результат, похожий на

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

Может ли это быть достигнуто без использования курсора?

Ответы [ 2 ]

1 голос
/ 25 января 2011

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 для метаданных. Кроме того, это возможно - лучше сохранить соответствующую группу при вставке строк метадата.

UPD : я проверил это и исправил ошибки в моем запросе, а не он работает и дает результат, как в первом вопросе.

UPD2 : И рекомендуемые индексы:


create clustered index IX_Metadata on Metadata (DocumentValue)
create nonclustered index IX_Doc_StartValue on Doc (DocumentStartValue)
1 голос
/ 25 января 2011

Что-то вроде, извините, не могу проверить

;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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...