簡體   English   中英

SQL - 根據另一個表將表中的行分配到不均勻的組中

[英]SQL - Distribute rows from a table into uneven groups, based on another table

假設我有桌子人:

name | group
------------
bob  | -
bill | -
joe  | -
tim  | -
mei  | -
jen  | -
ben  | -
lyn  | -
eli  | -
fin  | -
hal  | -
kim  | -

和表組:

group | max_people
------------------
A     | 2
B     | 5
C     | 3

如何編寫一個從People表返回行的查詢,每行按順序分配給一個組,直到分配了所有10個人。

分配給組的人數不能超過該組的max_people值。 因此,如果已達到所有組的最大值,則應保留未分配的剩余人員。

所以輸出應該如下:

name | group
------------
bob  | A
bill | A
joe  | B
tim  | B
mei  | B
jen  | B
ben  | B
lyn  | C
eli  | C
fin  | C
hal  | -
kim  | -

非常感激!

在人員表上創建一個游標

DECLARE @name VARCHAR(50),@groupname varchar(10)  

DECLARE people_cursor CURSOR FOR  
SELECT name 
FROM people
 OPEN people_cursor
FETCH NEXT FROM people_cursor INTO @name   

WHILE @@FETCH_STATUS = 0   
BEGIN   
       select top 1 @groupname = group from groups table where max_people>0  
       update  people set group =  @groupname where name = @name

       update group  set  max_people= max_people -1 where group =  @groupname 

       FETCH NEXT FROM people_cursor INTO @name   
END   

CLOSE people_cursor
DEALLOCATE people_cursor

首先,你可以像這樣根據max_people列的值復制組

WITH Repeater (Repeat ) AS (
    SELECT 1 AS Repeat UNION ALL
    SELECT Repeat + 1 FROM Repeater WHERE Repeat < 99
),
GroupsRepeat AS (
    SELECT [group], max_people,  ROW_NUMBER() OVER(ORDER BY [group] ASC) AS row_num
    FROM  Groups INNER JOIN Repeater ON Groups.max_people >= Repeater.Repeat    
)

然后,您可以將定義的GroupsRepeat表與People表連接,如下所示

SELECT People.name, 
          COALESCE(GroupsRepeat.[group], People.[group]) AS [group] 
   FROM   (SELECT *, 
                  ROW_NUMBER() OVER(ORDER BY [group]) AS row_num 
           FROM   People) People 
          LEFT JOIN GroupsRepeat 
                 ON GroupsRepeat.row_num = People.row_num; 

你可以在這里看到一個演示

給你的名字編號,例如

select name, row_number() over (order by name) as num
from names

為您的組分配編號范圍:

select 
  grp, 
  sum(max_people) over (order by grp) - max_people + 1 as from_num,
  sum(max_people) over (order by grp) as till_num
from groups

結合這兩個:

select n.name, g.grp
from
(
  select name, row_number() over (order by name) as num
  from names
) n
left join 
(
  select 
    grp, 
    sum(max_people) over (order by grp) - max_people + 1 as from_num,
    sum(max_people) over (order by grp) as till_num
  from groups
) g on n.num between g.from_num and g.till_num;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM