Apakah ada cara untuk bergabung dengan setiap baris TableA ke baris TableB yang lebih kecil dengan mengulangi TableB namun berkali-kali dibutuhkan?


8

Maaf untuk judul yang membingungkan, saya tidak yakin harus menulis apa di sana.

Saya punya tabel beberapa ratus catatan. Saya perlu menetapkan setiap rekaman tabel ini ke tabel dinamis pengguna yang jauh lebih kecil, dan pengguna harus mengganti dengan catatan apa yang mereka dapatkan.

Misalnya, jika TableA adalah

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

dan TableB adalah

Row_Number () Id
1 1
2 2
3 3

Saya perlu hasil akhir yang ditetapkan

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

Saya telah berhasil melakukan sesuatu yang sedikit berantakan menggunakan operator mod, tetapi saya ingin tahu apakah permintaan yang sama ini dapat dijalankan tanpa tabel temp dan variabel.

Tabel temp digunakan karena TableA sebenarnya adalah Fungsi yang Ditentukan Pengguna yang mengubah string yang dibatasi koma menjadi sebuah tabel, dan saya memerlukan Hitungan objek dari 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

Adalah penting bahwa UserIds berganti juga. Saya tidak bisa menetapkan 1/3 atas catatan untuk User1, 1/3 kedua catatan untuk User2, dan 1/3 ketiga catatan untuk User3.

Juga, UserIds perlu mempertahankan urutan di mana mereka awalnya dimasukkan, itulah sebabnya saya punya Row_Number() OVER (ORDER BY (SELECT 1))di tabel Pengguna

Apakah ada cara untuk menggabungkan tabel ini dalam satu permintaan jadi saya tidak perlu menggunakan tabel temp dan variabel?

Saya menggunakan SQL Server 2005

Jawaban:


12

Cara lain untuk menghindari tabel temp adalah:

;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;

Ahhh aku tidak menyadari aku bisa menggunakan Count(*)dengan OVER()untuk mendapatkan jumlah record tanpa benar-benar pengelompokan catatan. Hal ini memungkinkan saya untuk menyingkirkan tabel temp dan variabel, terima kasih :)
Rachel

6

Ya, Anda bisa melakukan ini tanpa tabel temp:

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;

Lihat di sini untuk demo SQLFiddle


Meskipun ini menghilangkan tabel temp dan variabel, saya tidak suka fakta bahwa Anda perlu menjalankan sub query untuk setiap record :)
Rachel

4
@Rachel hanya karena itulah yang dinyatakan tidak berarti itulah cara dieksekusi.
Aaron Bertrand

@ AaronBertrand Itu benar, tetapi tidak suka mempercayai kompiler SQL untuk menentukan rencana eksekusi yang baik untuk saya lebih dari yang seharusnya. Ini menyebabkan masalah bagi saya di masa lalu :)
Rachel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.