要求发放正确的徽章并模糊其余部分

Request to give out right badges and blurry the rest

我有一个 table badges,其中列出了所有可用的徽章(badge_id、名称、描述...),一个 table users列出所有用户(user_id、姓名、...)和一个 table users_badges 保存所有获得的徽章(id、badge_id、user_id)。

如果用户 1 获得徽章 5,条目 (x, 5, 1) 将被放入 users_badges(用户只能获得每个徽章一次)。

为了向每个用户显示她到目前为止获得了哪些徽章以及哪些徽章仍未获得,我想列出她的所有徽章,而获得的徽章是彩色的,未获得的徽章是灰色的。

为此,我需要一个适当的 SQL 查询 - 这就是我正在努力解决的问题。可能的输出将是一个不同的列表,其中包含所有徽章和旁边特定用户的 user_id;如果她还没有获得徽章,则为 NULL。

第一次尝试:

SELECT * FROM badges
LEFT JOIN users_badges ON badges.id = users_badges.badge_id
WHERE users_badges.user_id = ".$row['user_id']." OR users_badges.user_id IS NULL
ORDER BY badges.id

问题:这仅适用于拥有其他用户的所有徽章或更多徽章的用户,因为 WHERE 踢出了仅属于其他用户的徽章。

第二次尝试:

SELECT * FROM badges
LEFT JOIN users_badges ON badges.id = users_badges.badge_id
ORDER BY badges.id

问题:如果徽章由多个用户拥有,则会多次列出。添加 DISTINCT 不会解决问题,因为行已经不同(不同的用户 ID)。 也许可以从这种方法出发,剔除所请求行以外的所有具有 user_ids 的行,但前提是她已经获得了徽章(以确保所有非拥有的徽章也被列出(在灰色)?

对您的数据结构做出一些假设,我为此示例创建了虚拟表:

create table #badges
(
    badge_id int,
    [name] varchar(50),
    [description] varchar(50)
)

create table #users
(
    [user_id] int,
    [name] varchar(50)
)

create table #users_badges
(
    id int,
    badge_id int,
    [user_id] int
)

insert into #badges
values
    (1,'Starter Badge','It''s your first time.'),
    (2,'Rookie Badge','You''re just getting started.'),
    (3,'Intermediate Badge','Now you''re starting to get the hang of this.'),
    (4,'Expert Badge','You are a master!')

insert into #users
values
    (1,'John Smith'),
    (2,'Alice Johnson'),
    (3,'Phillip Black'),
    (4,'Sarah Goodwell'),
    (5,'Ian Hunter')

insert into #users_badges
values
    (1,1,1),
    (2,1,2),
    (3,1,3),
    (4,1,4),
    (5,2,1),
    (6,2,2),
    (7,2,4),
    (8,3,5),
    (9,4,1),
    (10,4,2)

我认为这就是您要查找的结果(此处,具体查看 user_id 为 1 的用户 - John Smith):

select 
    b.*,  
    case when ub.id is not null then 'Earned' else null end as badgeStatus
from #badges b
left join #users_badges ub on b.badge_id = ub.badge_id and ub.[user_id] = 1

这里列出了所有徽章并显示了 John 获得的徽章:

/------------------------------------------------------------------------|--------\
| id | name               | description                                  | status |
|----|--------------------|----------------------------------------------|--------|
|  1 | Starter Badge      | It's your first time.                        | Earned |
|  2 | Rookie Badge       | You're just getting started.                 | Earned |
|  3 | Intermediate Badge | Now you're starting to get the hang of this. | NULL   |
|  4 | Expert Badge       | You are a master!                            | Earned |
\---------------------------------------------------------------------------------/