0

SQL Server 2008 OrderIds と ItemIds を持つ 2 つのテーブルがあります。同一のアイテム ID の数が最大である 2 番目のテーブルの OrderId にリンクされた、最初のテーブルの各 OrderId を含む結果のテーブルが必要です。

2 つのループを使用してこれを行うスクリプトを作成しましたが、これらのテーブルの OrderId の数が多い場合 (~1000)、ループを 1000x1000 回実行する必要があり、長すぎる可能性があります。これはより良い方法で達成できますか?

以下の私の既に書かれたスクリプトを参照してください:

drop table #Match, #OrderRec, #OrderSent

create table #Match(
    OrderIdRec  int NULL,
    OrderIdSent int NULL)

create table #OrderRec(
    OrderIdRec      int     NOT NULL,
    ItemId          int         NULL)

create table #OrderSent(
    OrderIdSent     int     NOT NULL,
    ItemId          int         NULL)

insert #OrderRec values (1, 1)
insert #OrderRec values (1, 5)
insert #OrderRec values (1, 7)
insert #OrderRec values (1, 4)
insert #OrderRec values (1, 15)
insert #OrderRec values (1, 10)

insert #OrderRec values (2, 21)
insert #OrderRec values (2, 15)
insert #OrderRec values (2, 21)
insert #OrderRec values (2, 26)

insert #OrderRec values (5, 4)
insert #OrderRec values (5, 3)
insert #OrderRec values (5, 12)
insert #OrderRec values (5, 1)

insert #OrderSent values (121, 1)
insert #OrderSent values (121, 2)
insert #OrderSent values (121, 5)
insert #OrderSent values (121, 10)
insert #OrderSent values (121, 9)

insert #OrderSent values (122, 6)
insert #OrderSent values (122, 7)
insert #OrderSent values (122, 9)
insert #OrderSent values (122, 11)

insert #OrderSent values (142, 1)
insert #OrderSent values (142, 12)
insert #OrderSent values (142, 4)
insert #OrderSent values (142, 11)

set nocount on

declare @OrderIdRec int,
        @OrderIdSent int,
        @cnt numeric(10),
        @cnt_max numeric(10),
        @OrderIdSentMax int

select @OrderIdRec = MIN(OrderIdRec)
from #OrderRec

while ISNULL(@OrderIdRec,0) > 0
begin

    select @OrderIdSent = MIN(OrderIdSent)
    from #OrderSent

    set @cnt_max = 0
    set @OrderIdSentMax = NULL

    while ISNULL(@OrderIdSent,0) > 0
    begin

        set @cnt = 0

        select @cnt = COUNT(*)
        from #OrderRec r
            inner join #OrderSent t
        on t.ItemId = r.ItemId
        where r.OrderIdRec = @OrderIdRec
        and t.OrderIdSent = @OrderIdSent

        if isnull(@cnt, 0) > @cnt_max
        begin
            set @cnt_max = @cnt
            set @OrderIdSentMax = @OrderIdSent      
        end

        select @OrderIdSent = MIN(OrderIdSent)
        from #OrderSent
        where OrderIdSent > @OrderIdSent
    end

    insert #Match(
        OrderIdRec,
        OrderIdSent)
    values (@OrderIdRec, @OrderIdSentMax)

    select @OrderIdRec = MIN(OrderIdRec)
    from #OrderRec
    where OrderIdRec > @OrderIdRec
end

select * 
from #Match
order by OrderIdRec

実際のスクリプトは set nocount on で始まります。その前にあるのは、操作するデータのセットを作成することだけです。

結果は次のとおりです。

OrderIdRec  OrderIdSent
1            121
2            NULL
5            142
4

2 に答える 2

0
;WITH s AS 
(
  SELECT OrderIdRec, OrderIdSent, 
    rn = ROW_NUMBER() OVER (PARTITION BY OrderIdRec ORDER BY c DESC)  
  FROM
  (
    SELECT r.OrderIdRec, s.OrderIdSent, 
      c = COUNT(*) OVER (PARTITION BY r.OrderIdRec, s.OrderIdSent)
    FROM #OrderRec AS r
    INNER JOIN #OrderSent AS s
    ON r.ItemId = s.ItemId
  ) AS s2
),
d AS (SELECT OrderIdRec FROM #OrderRec GROUP BY OrderIdRec)
SELECT d.OrderIdRec, s.OrderIdSent
FROM d LEFT OUTER JOIN s
ON d.OrderIdRec = s.OrderIdRec AND s.rn = 1
ORDER BY d.OrderIdRec;
于 2013-08-29T03:32:04.330 に答える