TableBを繰り返すことによってTableAのすべての行を小さなTableBの行に結合する方法はありますか?


8

タイトルが紛らわしいので申し訳ありませんが、そこに何を書けばよいかわかりませんでした。

数百レコードのテーブルがあります。このテーブルの各レコードをユーザーのはるかに小さい動的テーブルに割り当てる必要があります。ユーザーは、割り当てられるレコードを交互に切り替える必要があります。

たとえば、TableAが

Row_Number()ID
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10

そしてTableBは

Row_Number()ID
1 1
2 2
3 3

私は最終結果セットが必要です

UserId RecordId
1 1
2 2
3 3
1 4
2 5
3 6
1 7
2 8
3 9
1 10

私はなんとか乱雑にmod演算子を使用して何かを行うことができましたが、この同じクエリを一時テーブルと変数なしで実行できるかどうか知りたいと思いました。

一時テーブルが使用されるのは、TableAが実際にはコンマ区切りの文字列をテーブルに変換するユーザー定義関数であり、UDFからのオブジェクトのカウントが必要だからです。

-- Converts a comma-delimited string into a table
SELECT Num as [UserId], Row_Number() OVER (ORDER BY (SELECT 1)) as [RowNo]
INTO #tmpTest
FROM dbo.StringToNumSet('2,3,1', ',') 

DECLARE @test int
SELECT @test = Count(*) FROM #tmpTest

SELECT *
FROM #tmpTest as T1
INNER JOIN (
    SELECT Top 10 Id, Row_Number() OVER (ORDER BY SomeDateTime) as [RowNo]
    FROM TableA WITH (NOLOCK)
) as T2 ON T1.RowNo = (T2.RowNo % @test) + 1

UserIdも代替することが重要です。レコードの上位1/3をUser1に、2番目のレコードをUser2に、3番目の1/3をUser3に割り当てることができません。

また、UserIdは最初に入力された順序を維持する必要があるためRow_Number() OVER (ORDER BY (SELECT 1))、ユーザーのテーブルに

これらのテーブルを1つのクエリで結合する方法はありますか?そのため、一時テーブルと変数を使用する必要はありませんか?

SQL Server 2005を使用しています

回答:


12

一時テーブルを回避する別の方法は次のとおりです。

;WITH tmpTest AS
(
    SELECT  Num as [UserId]
            , Row_Number() OVER (ORDER BY (SELECT 1)) as [RowNo]
            , COUNT(*) OVER() AS Quant
    FROM dbo.StringToNumSet('2,3,1', ',') 
)
SELECT *
FROM tmpTest as T1
INNER JOIN 
    (
        SELECT Top 10 Id
            , Row_Number() OVER (ORDER BY SomeDateTime) as [RowNo]
        FROM TableA WITH (NOLOCK)
    ) as T2 ON T1.RowNo = (T2.RowNo % Quant) + 1;

ああ私は、私が使用することができます実現していないCount(*)OVER()、実際にレコードをグループ化することなく、レコード数を取得します。これにより、一時テーブルと変数の両方
Rachel

6

はい、一時テーブルなしでこれを行うことができます:

with w as (select usr_id, row_number() over (order by usr_id) as usr_ordinal from usr)
select record_id, ( select usr_id
                    from w
                    where usr_ordinal=1+(record_ordinal%(select count(*) from w))
                  ) as usr_id
from ( select record_id, row_number() over (order by record_id) as record_ordinal 
       from record ) as z;

SQLFiddleデモについては、こちらをご覧ください


これは一時テーブルと変数を取り除きますが、すべてのレコードに対してサブクエリを実行する必要があるという事実は好きではありません:)
Rachel

4
@Rachelが宣言されているからといって、それが実行方法であることを意味するわけではありません。
Aaron Bertrand

@AaronBertrand確かにそうですが、SQLのコンパイラを信頼して、必要以上に私のために適切な実行計画を決定するのは好きではありません。それは過去に私に問題を引き起こしました:)
Rachel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.