我有一个有趣的问题,将表分成一组。我有一群游客 - 每个人说一种语言和/或是家庭的一部分。 我需要将表格分组,但我想将家庭和类似的语言说话者放在一起。分区表,但基于多列组合在一起
假设我想将游客分成最多3人的团体(如果一个团体必须更大,那是可以接受的)。该解决方案不必非常聪明,以至于完全填补所有组织,但我正在尽力而为。
输入:
TouristID | LanguageID | FamilyID
---------------------------------
1 | 1 | 1
2 | 1 | 1
3 | 1 | 1
4 | 2 | 1
5 | 3 | 2
6 | 4 | 2
7 | 5 | 3
8 | 5 | 4
9 | 7 | 5
期望的结果:
TouristID | GroupID
-------------------
1 | 1
2 | 1
3 | 1
4 | 1
5 | 2
6 | 2
7 | 3
8 | 3
9 | 2
组1是由所有语言1个扬声器,包括不能被排除在一个家族成员形成。
组2由两个家庭成员形成(5,6)和一个随机构件(9),以使该组的3
组3由两个相同的语言扬声器(7,8形成)
我所做的:
INSERT TouristGroup
SELECT
t.TouristID,
DENSE_RANK() OVER (ORDER BY GroupID) AS [GroupID]
FROM Tourists t
CROSS APPLY (
SELECT MIN(TouristID) AS [GroupID]
FROM Tourists t2
WHERE
(t2.LanguageID = t.LanguageID
OR t2.FamilyID = t.FamilyID)
) x;
INSERT Groups
SELECT GroupID, COUNT(*)
FROM TouristGroup
GROUP BY GroupID;
declare
@matchID int = 0,
@currentCount int,
@desiredCount int = 0,
@candidateGroupID int = null,
@chunk int = 1
while exists (
select null
from Groups g
left join Matches m
on m.GroupID = g.GroupID
where m.GroupID is null
)
begin
set @currentCount = null
set @candidateGroupID = null
select
@currentCount = isnull(SUM([Count]), 0)
from Matches m
join Groups g
on g.GroupID = m.GroupID
where m.MatchID = @matchID
if @CurrentCount is not null
begin
set @desiredCount = @chunk - @desiredCount
select top 1
@candidateGroupID = g.GroupID
from Groups g
left join Matches m
on m.GroupID = g.GroupID
where g.[Count] <= @desiredCount
and m.GroupID is null
order by [Count] DESC
if @candidateGroupID is not null
begin
insert Matches
select @matchID, @candidateGroupID
end
else begin
set @matchID = @matchID + 1
end
end
else begin
set @matchid = @matchID + 1
end
end
问题
是否有更好的方法来分区表,但基于多列将行分组在一起?
你说的是实际的[table partitioning](http://msdn.microsoft.com/en-us/library/ms190787.aspx)?或者为结果集分组数据? – supergrady 2013-03-21 02:39:00
分组。在我上面创建的例子中,我需要将游客分成几组,但我想让家人和类似语言的人聚在一起。对于那些不符合3人小组的人,他们被合并。即游客9与5和6结合 – 2013-03-21 05:30:56
什么版本的SQL Server? – 2013-03-21 19:50:54