我们有一个包含重复用户记录的数据库,我需要根据以下几个因素选择“最佳”用户:
基于这些条件,我提出了类似以下查询的内容(实际查询过于敏感)。
SELECT TOP 1 u.[UserId]
FROM [dbo].[Users] u
LEFT OUTER JOIN [dbo].[UserMemberships] um
ON u.[UserId] = um.[UserId]
LEFT OUTER JOIN [dbo].[Memberships] m
ON um.[MembershipId] = m.[MembershipId]
WHERE u.[Email] = @Email
ORDER BY m.[Order] ASC, um.[Expires] DESC, u.[Created] DESC
我遇到的问题是会员的订购与到期。例如,如果有两个具有不同级别成员资格的重复用户,我通常会希望用户具有“最佳”成员资格级别(基于订单),但如果该成员资格已过期,我希望那个未过期的用户,即使它是较低的水平。但是,我不能简单地排除过期的会员资格,因为我需要选择具有会员资格的用户(即使它已过期)而不是会员资格。
基本上,按会员顺序排序然后过期日期涵盖了大多数情况,但在这个特定情况下,订单应该是过期日期,然后是会员顺序。我可以对查询进行哪些修改以涵盖此边缘情况?
答案 0 :(得分:2)
这样的事情怎么样?通过使用一些Case
语句来创建数字排名列,您仍然可以在查询中保留过期记录,但为它们分配较低的值,以便必须首先评估活动成员资格:
SELECT TOP 1 u.[UserId],
Case um.[Expires]
When null then 9999 --Inactive Membership
When >= GetDate() then 1 --Expired Membership
Else 0 --Active Membership
End as ActiveRank,
Case m.[Order]
When null then 9999 --No Membership
Else Order --Membership Ranking
End as MembershipRank
FROM [dbo].[Users] u
LEFT OUTER JOIN [dbo].[UserMemberships] um
ON u.[UserId] = um.[UserId]
LEFT OUTER JOIN [dbo].[Memberships] m
ON um.[MembershipId] = m.[MembershipId]
WHERE u.[Email] = @Email
ORDER BY ActiveRank ASC, MembershipRank ASC, u.[Created] DESC
注意:我不太清楚你在Created
字段中做了什么,所以我把它留在了订单中。
这意味着以下内容成立:
ActiveRank
会将订单拆分为两个不同的组...列表的上半部分将按活动成员资格排序,而较低的部分将按过期或不存在的成员资格排序。MembershipRank
将根据排名优先排序(将空值或不存在的成员资格推送到列表过期成员资格部分的最底部。答案 1 :(得分:1)
这是psuedocode,我将如何解决这个问题:
SELECT TOP 1 FROM (
SELECT UserId, 1 AS rnk
FROM Table
WHERE {most desireable conditions are true}
UNION ALL
SELECT UserId, 2 AS rnk
FROM Table
WHERE {2nd most desireable conditions are true}
UNION ALL
SELECT UserId, 3 AS rnk
FROM Table
WHERE {3rd most desireable conditions are true}
...
) u
ORDER BY rnk ASC, {Secondary OrderBys like ExpDate etc}
答案 2 :(得分:1)
我之前所做的是使用案例陈述来为我的不同因素提供权重。然后,您可以根据总体重量选择要执行的操作。例如:
SELECT TOP 1
CASE WHEN Expires >= GETDATE() THEN 10 ELSE 0 END
+
MemberLevel --Assuming this is some number that already ranks the member based on level
+
CASE WHEN IsMember THEN 2 ELSE 0 END MyRank
FROM [Your tables]
ORDER BY 1 Desc