2017-05-29 23 views
1

假设我有表的人:SQL - 从表分配行到不均匀组,根据其它表

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

非常感谢!

+1

表没有为了自己的行。那么“顺序”意味着什么? – philipxy

回答

1

给你的名字编号,例如

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

虽然所有的答案都有效,但这是最简单/最直接的方法。谢谢! –

1

创建上百姓餐桌光标

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 
1

首先,你可以在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; 

您可以看到演示here