我有以下数据集,它代表项目和活动之间的映射:
ProjectID ActivityID
A A
B B
B C
D D
E D
M N
我想基于以下规则计算ID:
a project that maps 1-1 with an activity:
A - A
M - N
one project that maps to multiple activities:
B - B
B - C
one activity that maps to multiple projects:
D - D
E - D
这会产生:
ProjectID Activity CalculatedID
A A 1
B B 2
B C 2
D D 3
E D 3
M N 4
我希望那里有足够的信息,任何想法都会受到赞赏。我特别感兴趣的是看一套基于集合的方法。
- 更新:关于答案的说明 - 我将@Erwin采用的方法描述为映射的分类,与@mellamokb(建立在@ CodeByMoonlight的解决方案上)提供的解决方案相比,该解决方案分配了一个seqential ID。你的两个解决方案都帮助了我,谢谢你们!
答案 0 :(得分:2)
这有点令人费解,但它有效:
SELECT ProjectID, ActivityID,
DENSE_RANK() OVER(ORDER BY ProjectID) +
DENSE_RANK() OVER(ORDER BY ActivityID) -
ROW_NUMBER() OVER(ORDER BY ProjectID, ActivityID) AS CalculatedID
FROM MyTable
当重复ProjectID或ActivityID发生时,DENSE_RANK的两种用途会产生对ROW_NUMBER创建偏移的效果。
答案 1 :(得分:2)
这是一个基于@CodeByMoonlight
的答案构建的解决方案,它处理活动ID和projectID可以交错的情况,即,活动ID的ID高于其他一些条目,但projectID的ID低于其他条目输入:
SELECT
D.ProjectID,
D.ActivityID,
-- generate id based on the three different scenarios
-- 1) projects with 1-many activities, use project id
-- 2) activities with 1-many projects, use activity id
-- 3) 1-1, use project id
DENSE_RANK() over (order by
case
when P.ProjectID is not null then P.ProjectID
when A.ActivityID is not null then A.ActivityID
else D.ProjectID
end
) as Identifier
from
MyTable D
left join
(
-- projects with 1-many activities
SELECT ProjectID
FROM MyTable
group by ProjectID
having Count(ActivityID) > 1
) P on P.ProjectID = D.ProjectID
left join
(
-- activities with 1-many projects
SELECT ActivityID
FROM MyTable
group by ActivityID
having Count(ProjectID) > 1
) A on A.ActivityID = D.ActivityID
示例输入:
B C
A A
B B
B G
D D
B F
E D
M N
示例输出:
A A 1
B B 2
B G 2
B F 2
B C 2
E D 3
D D 3
M N 4
答案 2 :(得分:1)
;WITH p AS (
SELECT ProjectID FROM tbl GROUP BY ProjectID HAVING count(*) > 1
),a AS (
SELECT ActivityID FROM tbl GROUP BY ActivityID HAVING count(*) > 1
)
SELECT t.*
,CASE
WHEN p.ProjectID IS NOT NULL
AND a.ActivityID IS NOT NULL THEN 4 -- n:m (missing in question!)
WHEN p.ProjectID IS NOT NULL THEN 2 -- 1:n
WHEN a.ActivityID IS NOT NULL THEN 3 -- n:1
ELSE 1 -- 1:1
END AS CalculatedID
FROM tbl AS t
LEFT JOIN p ON p.ProjectID = t.ProjectID
LEFT JOIN a ON a.ActivityID = t.ActivityID
说明:
p
中找到所有具有多个活动的项目。a
中查找包含多个项目的所有活动。我添加了问题中缺少的案例4(n:m) 请参阅working demo on data.SE。