【发布时间】:2019-02-19 14:23:23
【问题描述】:
您可以运行所有这些 SQL 并查看结果 here。
- 跳到结果和随之而来的问题,了解问题的实质。
我有一张俱乐部表(一个俱乐部,如一个团体或组织中的一个人,如“游泳俱乐部”或“针织俱乐部”)。
DECLARE @club TABLE (
Id INT
,Name NVARCHAR(255)
);
INSERT INTO @club VALUES
(1, 'Swim Club')
,(2, 'Knitting Club')
,(3, 'Bridge Club');
我有一个成员表。
DECLARE @member TABLE (
Id INT
,Name NVARCHAR(255)
);
INSERT INTO @member VALUES
(1, 'John Jones')
,(2, 'Sally Smith')
,(3, 'Rod Roosevelt')
,(4, 'Bobby Burns')
,(5, 'Megan Moore');
会员可以属于许多俱乐部,因此有一个会员表将俱乐部与会员联系起来(并且还描述了会费价格)。
DECLARE @membership TABLE (
Id INT
,Member INT --FK to @member
,Club INT --FK to @club
,Dues INT --the cost of membership
);
INSERT INTO @membership VALUES
(1,1,1,10)
,(2,1,2,5)
,(3,2,1,10)
,(4,2,3,20)
,(5,3,1,10)
,(6,3,2,5)
,(7,4,2,5)
,(8,4,3,20)
,(9,5,1,10)
,(10,5,3,20);
大多数会员只需支付相关的会费。但是,有些会员是由其他会员赞助的。因此,这些赞助会员的会费将由另一个会员(赞助商)支付。因此,我们有一个赞助表。赞助表将赞助商(支付会费)连接到特定俱乐部的赞助商(由赞助商支付会费)。因为赞助是特定于俱乐部的,所以赞助记录连接两个会员记录,而不是两个会员记录。
DECLARE @sponsorship TABLE (
Id INT
,Sponsee_Membership INT --FK to Sponsee's @membership record
,Sponsor_Membership INT --FK to Sponsor's @membership record
);
INSERT INTO @sponsorship VALUES
(1,5,1)
,(2,8,4)
,(3,9,3)
,(4,10,4);
为了全面了解我们的俱乐部/会员/赞助商,我们有:
SELECT
mship.Id AS 'Mship'
,mem.Name AS 'Member'
,c.Name AS 'Club'
,mship.Dues
,spons_mem.Name AS 'Sponsor'
FROM
@membership AS mship
JOIN @member AS mem
ON mship.Member = mem.Id
JOIN @club AS c
ON mship.Club = c.Id
LEFT JOIN @sponsorship AS spons
ON spons.Sponsee_Membership = mship.Id
LEFT JOIN @membership AS spons_mship
ON spons_mship.Id = spons.Sponsor_Membership
LEFT JOIN @member AS spons_mem
ON spons_mem.Id = spons_mship.Member;
这给了我们这些结果:
Mship Member Club Dues Sponsor
1 John Jones Swim Club 10 NULL
2 John Jones Knitting Club 5 NULL
3 Sally Smith Swim Club 10 NULL
4 Sally Smith Bridge Club 20 NULL
5 Rod Roosevelt Swim Club 10 John Jones
6 Rod Roosevelt Knitting Club 5 NULL
7 Bobby Burns Knitting Club 5 NULL
8 Bobby Burns Bridge Club 20 Sally Smith
9 Megan Moore Swim Club 10 Sally Smith
10 Megan Moore Bridge Club 20 Sally Smith
赞助应涵盖所有共享会员。
- 也就是说,如果 Sally 赞助 Bobby,任何时候他们都在同一个俱乐部,Sally 将被确定为 Bobby 的赞助商。
- 我们可以在
Mship=7和Mship=8行中看到这一点。 - Bobby 和 Sally 都在 Bridge 俱乐部,因此 Sally 被确定为 Bobby 的 Bridge 俱乐部会员资格的赞助商。
- Sally 不是 Knitting Club 的成员,因此 Bobby 的 Knitting Club 成员身份不会显示 Sally 作为赞助商。
抱歉,设置太长了。 这是我的实际问题:
- 如何确定缺少赞助的位置?
在示例中,我们有行Mship=5和Mship=6。 - 约翰是罗德的赞助人。
- 我们可以看到罗德游泳俱乐部会员的赞助。
- 罗德和约翰也是针织俱乐部的成员,
- 但Rod 并未将 John 作为其针织俱乐部会员资格的赞助商。
- 这是不正确的,这就是我所追求的。
- 我想查询所有这些缺失的赞助。
我可以使用游标/WHILE 循环来完成此操作,但我知道此类解决方案通常不会采用适当的基于集合的方法。对此的正确查询是什么样的? 非常感谢。
【问题讨论】:
-
问题出在你的数据模型上。您是否可以更改它,或者您是否必须使用此模型编写 SQL 解决方法?
-
听起来赞助不应该是会员之间的一对一关系,而是俱乐部会员和赞助商之间的关系。您的表
sponsorship需要一个额外的列(它链接到的俱乐部)。 -
再举一个例子,让我们以 3 个成员和 3 个俱乐部为例。珍妮、简和约翰以及国际象棋、网球和读书俱乐部。 John 属于所有 3,但 Jenny 只属于 Book and Tennis,而 Jane 只属于 Chess and Book。珍妮和简都是约翰的赞助商,这对国际象棋和网球俱乐部来说是有意义的,但读书俱乐部呢?你有“双重泡沫”吗? :)
-
是的,问题的根源在于数据模型。不幸的是,这无法修改。这种次优数据结构会产生一致的数据清理量。这个问题是关于定期运行的许多必需的清理查询之一。
-
@JClark 谢谢澄清。很高兴你找到答案。希望我整理您的问题/添加 rextester 和要点能让其他人更容易提供帮助!
标签: sql sql-server tsql