Re-coding/transforming SQL 值从链接数据到新列:为什么 CASE WHEN 返回多个值?
Re-coding/transforming SQL values into new columns from linked data: why is CASE WHEN returning multiple values?
我处理来自多个 table 的大量链接数据。因此,我 运行 遇到了一些挑战,包括重复数据删除和以更有意义的方式将值重新编码到新列中。
我的核心数据集是一个以行表示的人员级记录列表。但是,链接数据包括每个人的多行,这些数据基于他们被预订参加活动的日期、他们是否出现以及他们是否是我们组织的成员。通常有多个预订。失去会员资格并继续参加 events/cancel/etc 是可能的,但我们感兴趣的是他们是否曾经是会员,如果不是,这是他们与我们组织有过的最高级别的联系。
简而言之:如果他们曾经是会员,则需要优先考虑。
select distinct
a.ticketnumber
a.id
-- (many additional columns from multiple tables here)
case
when b.Went_Member >=1 then 'Member'
when b.Went_NonMember >=1 then 'Attended but not member'
when b.Going_NonMember >=1 then 'Going but not member'
when b.OptOut='1' then 'Opt Out'
when b.Cancelled >=1 then 'Cancelled'
when c.MemberStatus = '9' then 'Member'
when c.MemberStatus = '6' then 'Attended but not member'
when c.DateBooked > current_timestamp then 'Going but not member'
when c.OptOut='1' then 'Opt out'
when c.MemberStatus = '8' then 'Cancelled'
end [NewMemberStatus]
from table1 a
left join TableWithMemberStatus1 b on a.id = b.id
left join TableWithMemberStatus2 c on a.id = c.id
-- (further left joins to additional tables here)
order by a.ticketnumber
Table b 更准确,因为这些是我们的内部记录,而 table c 来自第三方。恼人的是,C 中的数字与我们决定的顺序不同,所以我不能 select 每个 ID 的最高值。
我的印象是 CASE 在 WHEN 语句的列表中下降,returns 第一个匹配值,但这会产生多行。例如:
ID
NewMemberStatus
989898
NULL
989898
Cancelled
777777
Member
111111
Cancelled
111111
Member
我觉得在 ORDER BY 或 GROUP BY 方面可能缺少一些我应该添加的东西?我在里面尝试了 COALESCE 和 CASE 但它没有用。我应该在括号中嵌套一些东西吗?
在您的查询中,您显示了所有行(所有预订),因为没有 WHERE
子句也没有聚合。但是您只希望每个人获得一个结果行。
你想要一个人最好的状态来自于内在table。如果内部 table 中没有此人的条目,您希望他们从第三方 table 获得最佳状态。通过按人汇总内部和第三方 table 中的行,您可以获得最佳状态。然后加入这个人。
我正在使用状态编号,因为这些可以订购(我使用 1 表示最佳状态(会员),所以我寻找最低状态)。最后,我将找到的数字替换为相关文本(例如 'Member' 表示状态 1)。
select
p.*,
case coalesce(i.best_status, tp.best_status)
when 1 then 'Member'
when 2 then 'Attended but not member'
when 3 then 'Going but not member'
when 4 then 'Opt out'
when 5 then 'Cancelled'
else 'unknown'
end as status
from person p
left join
(
select
person_id,
min(case when went_member >= 1 then 1
when went_nonmember >= 1 then 2
when going_nonmember >= 1 then 3
when optout = 1 then 4
when cancelled >= 1 then 5
end) as best_status
from internal_table
group by person_id
) i on i.person_id = p.person_id
left join
(
select
person_id,
min(case when MemberStatus = 9 then 1
when MemberStatus = 6 then 2
when DateBooked > current_timestamp then 3
when optout = 1 then 4
when memberstatus = 8 then 5
end) as best_status
from thirdparty_table
group by person_id
) tp on tp.person_id = p.person_id
order by p.person_id;
我处理来自多个 table 的大量链接数据。因此,我 运行 遇到了一些挑战,包括重复数据删除和以更有意义的方式将值重新编码到新列中。
我的核心数据集是一个以行表示的人员级记录列表。但是,链接数据包括每个人的多行,这些数据基于他们被预订参加活动的日期、他们是否出现以及他们是否是我们组织的成员。通常有多个预订。失去会员资格并继续参加 events/cancel/etc 是可能的,但我们感兴趣的是他们是否曾经是会员,如果不是,这是他们与我们组织有过的最高级别的联系。
简而言之:如果他们曾经是会员,则需要优先考虑。
select distinct
a.ticketnumber
a.id
-- (many additional columns from multiple tables here)
case
when b.Went_Member >=1 then 'Member'
when b.Went_NonMember >=1 then 'Attended but not member'
when b.Going_NonMember >=1 then 'Going but not member'
when b.OptOut='1' then 'Opt Out'
when b.Cancelled >=1 then 'Cancelled'
when c.MemberStatus = '9' then 'Member'
when c.MemberStatus = '6' then 'Attended but not member'
when c.DateBooked > current_timestamp then 'Going but not member'
when c.OptOut='1' then 'Opt out'
when c.MemberStatus = '8' then 'Cancelled'
end [NewMemberStatus]
from table1 a
left join TableWithMemberStatus1 b on a.id = b.id
left join TableWithMemberStatus2 c on a.id = c.id
-- (further left joins to additional tables here)
order by a.ticketnumber
Table b 更准确,因为这些是我们的内部记录,而 table c 来自第三方。恼人的是,C 中的数字与我们决定的顺序不同,所以我不能 select 每个 ID 的最高值。
我的印象是 CASE 在 WHEN 语句的列表中下降,returns 第一个匹配值,但这会产生多行。例如:
ID | NewMemberStatus |
---|---|
989898 | NULL |
989898 | Cancelled |
777777 | Member |
111111 | Cancelled |
111111 | Member |
我觉得在 ORDER BY 或 GROUP BY 方面可能缺少一些我应该添加的东西?我在里面尝试了 COALESCE 和 CASE 但它没有用。我应该在括号中嵌套一些东西吗?
在您的查询中,您显示了所有行(所有预订),因为没有 WHERE
子句也没有聚合。但是您只希望每个人获得一个结果行。
你想要一个人最好的状态来自于内在table。如果内部 table 中没有此人的条目,您希望他们从第三方 table 获得最佳状态。通过按人汇总内部和第三方 table 中的行,您可以获得最佳状态。然后加入这个人。
我正在使用状态编号,因为这些可以订购(我使用 1 表示最佳状态(会员),所以我寻找最低状态)。最后,我将找到的数字替换为相关文本(例如 'Member' 表示状态 1)。
select
p.*,
case coalesce(i.best_status, tp.best_status)
when 1 then 'Member'
when 2 then 'Attended but not member'
when 3 then 'Going but not member'
when 4 then 'Opt out'
when 5 then 'Cancelled'
else 'unknown'
end as status
from person p
left join
(
select
person_id,
min(case when went_member >= 1 then 1
when went_nonmember >= 1 then 2
when going_nonmember >= 1 then 3
when optout = 1 then 4
when cancelled >= 1 then 5
end) as best_status
from internal_table
group by person_id
) i on i.person_id = p.person_id
left join
(
select
person_id,
min(case when MemberStatus = 9 then 1
when MemberStatus = 6 then 2
when DateBooked > current_timestamp then 3
when optout = 1 then 4
when memberstatus = 8 then 5
end) as best_status
from thirdparty_table
group by person_id
) tp on tp.person_id = p.person_id
order by p.person_id;