从一张桌子到另一张桌子均匀地分发记录

时间:2017-08-03 12:55:40

标签: sql sql-server tsql sql-server-2012

我有3张桌子:

Users
-----
UserID (varchar)
Active (bit)

Refunds_Upload 
--------------
BorrowerNumber (varchar)

Refunds
-------
BorrowerNumber 
UserID

我首先选择Active = 1的所有UserID值。

我需要将Refunds_Upload中的记录插入退款,但我需要为每个活动用户ID 插入相同(或尽可能接近)的记录数。
例如,如果Refunds_Upload有20条记录而且Users表有5个人,其中Active = 1,那么我需要将每个UserID的4条记录插入表退款。

最终结果将是:

BorrowerNumber  UserID
105             Fred
110             Fred
111             Fred
115             Fred
120             Billy
122             Billy
123             Billy
125             Billy
130             Lucius
131             Lucius
133             Lucius
135             Lucius
138             Lucy
139             Lucy
140             Lucy
141             Lucy
142             Grady
143             Grady
144             Grady
145             Grady

当然,它不会总是达到每个用户的偶数记录,所以我也需要考虑到这一点。

1 个答案:

答案 0 :(得分:2)

首先运行它并检查它返回类似你要插入的内容,然后取消注释插入并实际执行它..

--INSERT INTO Refunds

SELECT
  numbered_u.UserID,
  numbered_ru.BorrowerNumber
FROM
  (SELECT u.*, ROW_NUMBER() OVER(ORDER BY UserID) - 1 as rown, SUM(CAST(Active as INT)) OVER() as count_users FROM Users u WHERE active=1) numbered_u
  INNER JOIN
  (SELECT ru.*, ROW_NUMBER() OVER(ORDER BY BorrowerNumber) - 1 as rown, COUNT(*) OVER() as count_ru FROM Refund_Uploads ru) numbered_ru
  ON
    ROUND(CAST(numbered_ru.rown AS FLOAT) / (count_ru / count_users)) = numbered_u.rown

逻辑:

我们为用户中的每个有趣(active = 1)行编号,我们也将它们全部计算在内。这应该返回给我们所有5个用户,编号为0到4,并且每行的ctr为5。

然后我们将它们加入到类似编号的Refund_Uploads列表中(比如20)。类似地,由于后来变得明显的数学原因,这些行将被编号为0到19。我们也计算所有这些行

然后我们将这两个数据集连接在一起,但条件是一系列值而不是精确值。逻辑是“refund_upload行号,除以_count_of_rows_there_should_be_per_user”(即0..19 /(20/5))= user_row_number。希望因此退回第0行到第3行,与用户0相关联,退回第4行至第7行与用户1相关联等等。

没有完整数据调试有点困难 - 我觉得可能需要在这里和那里进行一些+1 / -1调整。

我最初使用FLOOR但是切换到使用ROUND,因为我认为这可能适用于分配Refund / User中没有整数个分区的数字集合,例如你的240/13例子..希望有些用户会有18行,有些用户可能有19行